123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- 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);
- }
- }
|