|
@@ -0,0 +1,228 @@
|
|
|
|
+let bucket; //aws上传接口
|
|
|
|
+let bucketname = "ccrb"; //桶
|
|
|
|
+const partsize = 1 * 1024 * 1024; // 1MB
|
|
|
|
+
|
|
|
|
+//--------------------------分断上传保证稳定性
|
|
|
|
+//初始化上传
|
|
|
|
+async function 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: 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: "Q2SQw37HfolS7yeaR1Ndpy9Jl4E2YZKUuuy2muZR",
|
|
|
|
+ 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;
|
|
|
|
+}
|
|
|
|
+
|