awsupload.js 7.4 KB

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