root 5 months ago
parent
commit
dd6dff3837
1 changed files with 228 additions and 0 deletions
  1. 228 0
      js/Common/awsupload.js

+ 228 - 0
js/Common/awsupload.js

@@ -0,0 +1,228 @@
+let bucket; //aws上传接口
+let bucketname = "ccrb"; //桶
+const partsize = 1 * 1024 * 1024; // 1MB
+
+//--------------------------分断上传保证稳定性
+//初始化上传
+async function 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: bucketname
+        }
+    });
+    return bucket;
+}
+
+//初始化上传入口
+async function initMultipartUpload(file, folderid) {
+    const params = {
+        Bucket: bucketname,
+        Key: folderid + "/" + file.name
+    };
+    //创建一个续传通道
+    const data = await bucket.createMultipartUpload(params).promise();
+    return data.UploadId;
+}
+
+// 上传文件的某一部分
+async function uploadPart(file, keyname, uploadid, pn, start, end) {
+    //key可以设置为桶的相对路径,Body为文件, ACL最好要设置
+    var params = {
+        Bucket: 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 bucket.uploadPart(params).promise()
+        .then((data) => {
+            return { ETag: result.ETag, PartNumber: pn };
+        })
+        .catch((err) => {
+            return err;
+        });
+}
+
+// 完成分块上传
+async function completeMultipartUpload(parts, keyname) {
+    const params = {
+        Bucket: bucketname,
+        Key: keyname,
+        MultipartUpload: { Parts: parts },
+        UploadId: uploadid
+    };
+    await bucket.completeMultipartUpload(params).promise();
+}
+
+//中止分块上传
+async function abortMultipartUpload(key, uploadid) {
+    const params = {
+        Bucket: bucketname,
+        Key: key,
+        UploadId: uploadid
+    };
+    await bucket.abortMultipartUpload(params).promise();
+}
+
+// 实际的上传逻辑
+async function uploadFile(file, folderid) {
+    folderid = folderid || window.Guid.newGuid(); //分配到一个随机的id里
+    var keyname = folderid + "/" + file.name; //保存在指定的文件夹里
+    var uploadid = "";
+    try {
+        init(); // 初始化aws接口
+        // 初始化分块上传
+        uploadid = await initMultipartUpload(file, folderid);
+        // 分块上传文件
+        let parts = [];
+        let start = 0;
+        let end = 0;
+        let len = Math.ceil(file.length / partsize); //循环的长度
+        //循环上传
+        for (let i = 0; i < len; i++) {
+            start = i * partsize;
+            end = (i + 1) * partsize;
+            parts.push(await uploadPart(file, keyname, uploadid, i, start, end));
+        }
+        // 完成分块上传
+        await completeMultipartUpload(parts, uploadid);
+        return uploadid;
+    }
+    catch (error) {
+        // 如果出现错误,中止分块上传
+        console.error('An error occurred during file upload:', error);
+        await abortMultipartUpload(keyname, uploadid);
+    }
+}
+
+//--------------------------------下面支持断点续传
+
+//初始化亚马逊参数
+async function 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"; //设置区域
+    //桶的设置
+    bucket = new window.AWS.S3({
+        params: {
+            Bucket: bucketname
+        }
+    });
+    return bucket;
+}
+
+//获取当前文件是否有已上传断点信息
+async function getawscheckpoint(key) {
+    let partsinfo;
+    try {
+        const result = await bucket.listMultipartUploads({ Bucket: bucketname, Prefix: key }).promise();
+        //获取具体分片信息
+        if (result.Uploads.length) {
+            uploadid = result.Uploads[result.Uploads.length - 1].UploadId;
+            partsinfo = await bucket.listParts({ Bucket: bucketname, Key: key, UploadId: uploadid, }).promise();
+        }
+    } catch (err) {
+        console.log(err);
+    }
+    return { uploadid, partsinfo };
+}
+
+//分段上传
+async function awsuploadpart(filestate, file, uploadid, parts, key) {
+    var partarr = [];//已完成的数组
+    //已完成的分片,转化成提交格式
+    const completeparts = parts.map((_) => {
+        partarr.push(_.PartNumber);
+        return { PartNumber: _.PartNumber, ETag: _.ETag };
+    });
+    // 分块上传文件
+    let parts = [];
+    let uploadpart;
+    let start = 0;
+    let end = 0;
+    let len = Math.ceil(file.length / partsize); //循环的长度
+    if (partarr.length) {
+        filestate.status = "processing";
+        filestate.percent = parseInt((completeparts.length * 100) / count);
+    }
+    //循环上传
+    for (let i = 0; i < len; i++) {
+        start = i * partsize;
+        end = (i + 1) * partsize;
+        if (!partarr.includes(i)) {
+            uploadpart = await uploadPart(file, key, uploadid, i, start, end);
+            if (uploadpart.ETag != null) {
+                completeparts.push(uploadpart);
+                filestate.percent = parseInt((completeparts.length * 100) / count);
+            }
+
+            else {
+                filestate.status = "fail";
+                return;
+            }
+        }
+    }
+    //提交上传成功信息
+    await completeMultipartUpload(completeparts, uploadid);
+}
+
+//上传的接口
+async function awsupload(file, folderid, filestate) {
+    init(); //初始化桶
+    const key = (folderid || window.Guid.newGuid()) + "/" + file.name; //需要上传的文件名
+    filestate.percent = 0;
+    filestate.status = "start";
+    //上传的参数
+    var params = {
+        Bucket: bucketname,
+        Key: key
+    };
+    //设置桶上传文件
+    try {
+        //检查文件是否已上传
+        bucket.headObject(params, async (err, data) => {
+            // 没有上传成功,head方法会返回失败
+            if (err) {
+                //检查是否部分上传
+                const { uploadid, partsinfo } = await getawscheckpoint(key, bucket);
+                //如果已经部分存在,那么直接在节点续传
+                if (uploadid) {
+                    //断点续传
+                    awsuploadpart(filestate, file, uploadid, partsinfo.Parts, key);
+                }
+                //不存在,上传新的
+                else {
+                    const uploadid = await initMultiPartUpload(bucket, params); //初始化文件上传
+                    awsuploadpart(filestate, file, uploadid, [], key);
+                }
+            }
+            //如果已经上传成功了,那么直接返回状态百分百
+            else if (data) {
+                //data存在,上传成功
+                filestate.percent = 100;
+                filestate.status = "success";
+            }
+        });
+    }
+    catch (err) {
+        filestate.status = "error";
+        console.log(err);
+    }
+    return filestate;
+}
+