let bucket; //aws上传接口 let bucketname = "ccrb"; //桶 const partsize = 5 * 1024 * 1024; // 5MB //--------------------------分断上传保证稳定性 //初始化上传 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(key, file) { const params = { Bucket: bucketname, Key: key, ContentType: file.type, "ACL": "public-read" }; //创建一个续传通道 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, PartNumber: pn, UploadId: uploadid, Body: file.slice(start, end) }; const result = await bucket.uploadPart(params).promise(); return { ETag: result.ETag, PartNumber: pn }; } // 完成分块上传 async function completeMultipartUpload(parts, keyname, uploadid) { const params = { Bucket: bucketname, Key: keyname, MultipartUpload: { Parts: parts }, UploadId: uploadid }; return 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(keyname, file); // 分块上传文件 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, keyname, 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 uploadpart; let start = 0; let end = 0; let len = Math.ceil(file.size / partsize); //循环的长度 if (partarr.length) { filestate.status = "processing"; filestate.percent = parseInt((completeparts.length * 100) / len); } //循环上传 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 + 1, start, end); if (uploadpart.ETag != null) { completeparts.push(uploadpart); filestate.percent = parseInt((completeparts.length * 100) / len); } else { filestate.status = "fail"; return; } } } //提交上传成功信息 var data = await completeMultipartUpload(completeparts, key, uploadid); filestate.status = "success"; return data; } //上传的接口 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) { //断点续传 var data = await awsuploadpart(filestate, file, uploadid, partsinfo.Parts, key); return { data, key, uploadid }; } //不存在,上传新的 else { const uploadid = await initMultipartUpload(key, file); //初始化文件上传 var data = await awsuploadpart(filestate, file, uploadid, [], key); return { data, key, uploadid }; } } //如果已经上传成功了,那么直接返回状态百分百 else if (data) { //data存在,上传成功 filestate.percent = 100; filestate.status = "success"; return { data, key }; } }); } catch (err) { filestate.status = "error"; console.log(err); } }