|
@@ -0,0 +1,331 @@
|
|
|
+<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: "Q2SQw37HfolS7yeaR1Ndpy9Jl4E2YZKUuuy2muZR",
|
|
|
+ // }; //秘钥形式的登录上传
|
|
|
+ // 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) {
|
|
|
+ console.log(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: "Q2SQw37HfolS7yeaR1Ndpy9Jl4E2YZKUuuy2muZR",
|
|
|
+ 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]}`;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log(key);
|
|
|
+ // key = key.replace(/\s/g, "");
|
|
|
+ // key = encodeURIComponent(key);
|
|
|
+ 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>
|