123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- <template>
- <div class="uploadBox"></div>
- </template>
- <script>
- import "../../../../../../common/aws-sdk-2.235.1.min.js";
- export default {
- props:{
- index:{
- type:String,
- default:"0"
- },
- },
- data() {
- return {
- bucket: "", //aws上传接口
- bucketname: "ccrb", //桶
- uploadid: "",
- partsize: 10 * 1024 * 1024, //10MB 分片
- filestate: {
- status: "", //有 error(直接报错) 和 fail(上传的时候报错) 和 success(上传成功) 和 processing(上传中)
- percent: "", //(0-100的进度)
- },
- file: null,
- flag:true,
- };
- },
- watch: {
- filestate: {
- handler(newValue) {
- this.$emit("progressUpdate", {index:this.index,...newValue});
- },
- immediate: true,
- deep: true,
- },
- },
- methods: {
- //--------------------------分断上传保证稳定性
- //初始化上传
- // async init(){
- // const credentials = {
- // accessKeyId: "AKIATLPEDU37QV5CHLMH",
- // secretAccessKey: "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",
- // }; //秘钥形式的登录上传
- // window.AWS.config.update(credentials);
- // window.AWS.config.region = "cn-northwest-1"; //设置区域
- // //桶的设置
- // bucket = new window.AWS.S3({
- // params: {
- // Bucket: this.bucketname
- // }
- // });
- // return bucket;
- // },
- // 初始化上传入口
- async initMultipartUpload(key, file) {
- const params = {
- Bucket: this.bucketname,
- Key: key,
- ContentType: file.type,
- ACL: "public-read",
- };
- //创建一个续传通道
- const data = await this.bucket.createMultipartUpload(params).promise();
- return data.UploadId;
- },
- // 上传文件的某一部分
- async uploadPart(file, keyname, uploadid, pn, start, end) {
- //key可以设置为桶的相对路径,Body为文件, ACL最好要设置
- if(!this.flag)return;
- var params = {
- Bucket: this.bucketname,
- Key: keyname,
- // ContentType: file.type,
- PartNumber: pn,
- UploadId: uploadid,
- Body: file.slice(start, end),
- // "Access-Control-Allow-Credentials": "*",
- // ACL: "public-read",
- };
- const result = await this.bucket.uploadPart(params).promise();
- return { ETag: result.ETag, PartNumber: pn };
- },
- //完成分块上传
- async completeMultipartUpload(parts, keyname, uploadid) {
- if(!this.flag)return;
- const params = {
- Bucket: this.bucketname,
- Key: keyname,
- MultipartUpload: { Parts: parts },
- UploadId: uploadid,
- };
- return await this.bucket.completeMultipartUpload(params).promise();
- },
- async abortMultipartUpload(key, uploadid) {
- const params = {
- Bucket: this.bucketname,
- Key: key,
- UploadId: uploadid,
- };
- let data = await this.bucket.abortMultipartUpload(params).promise();
- this.$emit("delUpload",{index:this.index})
-
- },
- //--------------------------------下面支持断点续传
- //初始化亚马逊参数
- async init() {
- //秘钥形式的登录上传
- const credentials = {
- accessKeyId: "AKIATLPEDU37QV5CHLMH",
- secretAccessKey: "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",
- region: "cn-northwest-1",
- };
- window.AWS.config.update(credentials);
- // window.AWS.config.region = "cn-northwest-1"; //设置区域
- //桶的设置
- this.bucket = new window.AWS.S3({
- params: {
- Bucket: this.bucketname,
- },
- });
- return this.bucket;
- },
- //获取当前文件是否有已上传断点信息
- async getawscheckpoint(key) {
- let partsinfo;
- try {
- const result = await this.bucket
- .listMultipartUploads({ Bucket: this.bucketname, Prefix: key })
- .promise();
- //获取具体分片信息
- if (result.Uploads.length) {
- this.uploadid = result.Uploads[result.Uploads.length - 1].UploadId;
- partsinfo = await this.bucket
- .listParts({
- Bucket: this.bucketname,
- Key: key,
- UploadId: this.uploadid,
- })
- .promise();
- }
- } catch (err) {
- console.log(err);
- }
- return { uploadid: this.uploadid, partsinfo };
- },
- //分段上传
- async awsuploadpart(filestate, file, uploadid, parts, key) {
- var partarr = []; //已完成的数组
- //已完成的分片,转化成提交格式
- const completeparts = parts.map((_) => {
- partarr.push(_.PartNumber);
- return { PartNumber: _.PartNumber, ETag: _.ETag };
- });
- // 分块上传文件
- // parts = [];
- let uploadpart;
- let start = 0;
- let end = 0;
- let len = Math.ceil(file.size / this.partsize); //循环的长度
- if (partarr.length) {
- this.filestate.status = "processing";
- this.filestate.percent = parseInt((completeparts.length * 100) / len);
- }
- //循环上传
- for (let i = 0; i < len; i++) {
- if(!this.flag)break;
- start = i * this.partsize;
- end = (i + 1) * this.partsize;
- if (!partarr.includes(i+1)) {
- uploadpart = await this.uploadPart(
- file,
- key,
- uploadid,
- i + 1,
- start,
- end
- );
- if (uploadpart.ETag != null) {
- completeparts.push(uploadpart);
- partarr.push(uploadpart.PartNumber);
- this.filestate.status = "processing";
- this.filestate.percent = parseInt(
- (completeparts.length * 100) / len
- );
- } else {
- this.filestate.status = "fail";
- this.stopUpload();
- return;
- }
- }
- }
- //提交上传成功信息
- if(this.flag){
- let data = await this.completeMultipartUpload(
- completeparts,
- key,
- uploadid
- );
- this.filestate.status = "success";
- return data;
- }
- },
- //上传的接口
- async awsupload({ file = this.file, keyName, folderName }) {
- if (!file) return this.$message.error("请上传文件");
- this.init(); //初始化桶
- // const key = (folderid || uuidv4()) + "/" + file.name; //需要上传的文件名
- let key = "";
- if (keyName) {
- key = keyName;
- } else {
- if (folderName) {
- key = `${folderName}/${file.name}`;
- } else {
- key = `default/${file.name.split(".")[0] +
- new Date().getTime() +
- "." +
- file.name.split(".")[file.name.split(".").length - 1]}`;
- }
- }
- this.filestate = {
- percent: 0,
- status: "start",
- };
- this.filestate.percent = 0;
- this.filestate.status = "start";
- this.file = file;
- //上传的参数
- var params = {
- Bucket: this.bucketname,
- Key: key,
- };
- this.flag = true;
- //设置桶上传文件
- try {
- //检查文件是否已上传
- this.bucket.headObject(params, async (err, data) => {
- // 没有上传成功,head方法会返回失败
- if (err) {
- //检查是否部分上传
- const { uploadid, partsinfo } = await this.getawscheckpoint(
- key,
- this.bucket
- );
- //如果已经部分存在,那么直接在节点续传
- if (uploadid) {
- //断点续传
- this.$emit("startUpload", { index:this.index,key, uploadid });
- this.filestate.key = key;
- this.filestate.uploadid = uploadid;
- this.flag = true;
- let data = await this.awsuploadpart(
- this.filestate,
- file,
- uploadid,
- partsinfo.Parts,
- key
- );
- if(this.flag || this.filestate.percent==100)return this.$emit("success", {index:this.index, data, key, uploadid });
- // return {data,key,uploadid}
- }
- //不存在,上传新的
- else {
- const uploadid = await this.initMultipartUpload(key, file); //初始化文件上传
- this.$emit("startUpload", { index:this.index,key, uploadid });
- this.filestate.key = key;
- this.filestate.uploadid = uploadid;
- this.flag = true;
- let data = await this.awsuploadpart(
- this.filestate,
- file,
- uploadid,
- [],
- key
- );
- if(this.flag || this.filestate.percent==100)return this.$emit("success", {index:this.index, data, key, uploadid });
- // return {data,key,uploadid}
- }
- }
- //如果已经上传成功了,那么直接返回状态百分百
- else if (data) {
- //data存在,上传成功
- this.filestate.percent = 100;
- this.filestate.status = "success";
- let url = `https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/${key}`
- this.file = null;
- if(this.flag)return this.$emit("success", { index:this.index,data:{
- Key:key,
- Location:url,
- ETag:data.ETag,
- size:data.ContentLength,
- ServerSideEncryption:data.ServerSideEncryption,
- Bucket:this.bucketname
- } });
- // return {data,key,uploadid}
- }
- });
- } catch (err) {
- this.filestate.status = "error";
- this.stopUpload();
- console.log(err);
- }
- },
- // 停止上传
- stopUpload(){
- this.filestate.status = "stop";
- this.flag = false;
- }
- },
- mounted() {
- this.bucket = "";
- this.file = null;
- },
- };
- </script>
- <style scoped>
- .uploadBox {
- display: none;
- }
- </style>
|