awsupload.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. let bucket; //aws上传接口
  2. let bucketname = "ccrb"; //桶
  3. const partsize = 1 * 1024 * 1024; // 1MB
  4. //--------------------------分断上传保证稳定性
  5. //初始化上传
  6. async function init() {
  7. const credentials = {
  8. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  9. secretAccessKey: "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",
  10. }; //秘钥形式的登录上传
  11. window.AWS.config.update(credentials);
  12. window.AWS.config.region = "cn-northwest-1"; //设置区域
  13. //桶的设置
  14. bucket = new window.AWS.S3({
  15. params: {
  16. Bucket: bucketname
  17. }
  18. });
  19. return bucket;
  20. }
  21. //初始化上传入口
  22. async function initMultipartUpload(file, folderid) {
  23. const params = {
  24. Bucket: bucketname,
  25. Key: folderid + "/" + file.name
  26. };
  27. //创建一个续传通道
  28. const data = await bucket.createMultipartUpload(params).promise();
  29. return data.UploadId;
  30. }
  31. // 上传文件的某一部分
  32. async function uploadPart(file, keyname, uploadid, pn, start, end) {
  33. //key可以设置为桶的相对路径,Body为文件, ACL最好要设置
  34. var params = {
  35. Bucket: bucketname,
  36. Key: keyname,
  37. ContentType: file.type,
  38. PartNumber: pn,
  39. UploadId: uploadid,
  40. Body: file.slice(start, end),
  41. "Access-Control-Allow-Credentials": "*",
  42. ACL: "public-read",
  43. };
  44. const result = await bucket.uploadPart(params).promise()
  45. .then((data) => {
  46. return { ETag: result.ETag, PartNumber: pn };
  47. })
  48. .catch((err) => {
  49. return err;
  50. });
  51. }
  52. // 完成分块上传
  53. async function completeMultipartUpload(parts, keyname) {
  54. const params = {
  55. Bucket: bucketname,
  56. Key: keyname,
  57. MultipartUpload: { Parts: parts },
  58. UploadId: uploadid
  59. };
  60. await bucket.completeMultipartUpload(params).promise();
  61. }
  62. //中止分块上传
  63. async function abortMultipartUpload(key, uploadid) {
  64. const params = {
  65. Bucket: bucketname,
  66. Key: key,
  67. UploadId: uploadid
  68. };
  69. await bucket.abortMultipartUpload(params).promise();
  70. }
  71. // 实际的上传逻辑
  72. async function uploadFile(file, folderid) {
  73. folderid = folderid || window.Guid.newGuid(); //分配到一个随机的id里
  74. var keyname = folderid + "/" + file.name; //保存在指定的文件夹里
  75. var uploadid = "";
  76. try {
  77. init(); // 初始化aws接口
  78. // 初始化分块上传
  79. uploadid = await initMultipartUpload(file, folderid);
  80. // 分块上传文件
  81. let parts = [];
  82. let start = 0;
  83. let end = 0;
  84. let len = Math.ceil(file.length / partsize); //循环的长度
  85. //循环上传
  86. for (let i = 0; i < len; i++) {
  87. start = i * partsize;
  88. end = (i + 1) * partsize;
  89. parts.push(await uploadPart(file, keyname, uploadid, i, start, end));
  90. }
  91. // 完成分块上传
  92. await completeMultipartUpload(parts, uploadid);
  93. return uploadid;
  94. }
  95. catch (error) {
  96. // 如果出现错误,中止分块上传
  97. console.error('An error occurred during file upload:', error);
  98. await abortMultipartUpload(keyname, uploadid);
  99. }
  100. }
  101. //--------------------------------下面支持断点续传
  102. //初始化亚马逊参数
  103. async function init() {
  104. //秘钥形式的登录上传
  105. const credentials = {
  106. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  107. secretAccessKey: "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",
  108. region: "cn-northwest-1"
  109. };
  110. window.AWS.config.update(credentials);
  111. // window.AWS.config.region = "cn-northwest-1"; //设置区域
  112. //桶的设置
  113. bucket = new window.AWS.S3({
  114. params: {
  115. Bucket: bucketname
  116. }
  117. });
  118. return bucket;
  119. }
  120. //获取当前文件是否有已上传断点信息
  121. async function getawscheckpoint(key) {
  122. let partsinfo;
  123. try {
  124. const result = await bucket.listMultipartUploads({ Bucket: bucketname, Prefix: key }).promise();
  125. //获取具体分片信息
  126. if (result.Uploads.length) {
  127. uploadid = result.Uploads[result.Uploads.length - 1].UploadId;
  128. partsinfo = await bucket.listParts({ Bucket: bucketname, Key: key, UploadId: uploadid, }).promise();
  129. }
  130. } catch (err) {
  131. console.log(err);
  132. }
  133. return { uploadid, partsinfo };
  134. }
  135. //分段上传
  136. async function awsuploadpart(filestate, file, uploadid, parts, key) {
  137. var partarr = [];//已完成的数组
  138. //已完成的分片,转化成提交格式
  139. const completeparts = parts.map((_) => {
  140. partarr.push(_.PartNumber);
  141. return { PartNumber: _.PartNumber, ETag: _.ETag };
  142. });
  143. // 分块上传文件
  144. let parts = [];
  145. let uploadpart;
  146. let start = 0;
  147. let end = 0;
  148. let len = Math.ceil(file.length / partsize); //循环的长度
  149. if (partarr.length) {
  150. filestate.status = "processing";
  151. filestate.percent = parseInt((completeparts.length * 100) / count);
  152. }
  153. //循环上传
  154. for (let i = 0; i < len; i++) {
  155. start = i * partsize;
  156. end = (i + 1) * partsize;
  157. if (!partarr.includes(i)) {
  158. uploadpart = await uploadPart(file, key, uploadid, i, start, end);
  159. if (uploadpart.ETag != null) {
  160. completeparts.push(uploadpart);
  161. filestate.percent = parseInt((completeparts.length * 100) / count);
  162. }
  163. else {
  164. filestate.status = "fail";
  165. return;
  166. }
  167. }
  168. }
  169. //提交上传成功信息
  170. await completeMultipartUpload(completeparts, uploadid);
  171. }
  172. //上传的接口
  173. async function awsupload(file, folderid, filestate) {
  174. init(); //初始化桶
  175. const key = (folderid || window.Guid.newGuid()) + "/" + file.name; //需要上传的文件名
  176. filestate.percent = 0;
  177. filestate.status = "start";
  178. //上传的参数
  179. var params = {
  180. Bucket: bucketname,
  181. Key: key
  182. };
  183. //设置桶上传文件
  184. try {
  185. //检查文件是否已上传
  186. bucket.headObject(params, async (err, data) => {
  187. // 没有上传成功,head方法会返回失败
  188. if (err) {
  189. //检查是否部分上传
  190. const { uploadid, partsinfo } = await getawscheckpoint(key, bucket);
  191. //如果已经部分存在,那么直接在节点续传
  192. if (uploadid) {
  193. //断点续传
  194. awsuploadpart(filestate, file, uploadid, partsinfo.Parts, key);
  195. }
  196. //不存在,上传新的
  197. else {
  198. const uploadid = await initMultiPartUpload(bucket, params); //初始化文件上传
  199. awsuploadpart(filestate, file, uploadid, [], key);
  200. }
  201. }
  202. //如果已经上传成功了,那么直接返回状态百分百
  203. else if (data) {
  204. //data存在,上传成功
  205. filestate.percent = 100;
  206. filestate.status = "success";
  207. }
  208. });
  209. }
  210. catch (err) {
  211. filestate.status = "error";
  212. console.log(err);
  213. }
  214. return filestate;
  215. }