put_sign.html 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>Ajax Put 上传(服务端计算签名)</title>
  6. <style>
  7. h1,
  8. h2 {
  9. font-weight: normal;
  10. }
  11. #msg {
  12. margin-top: 10px;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <h1>Ajax Put 上传(服务端计算签名)</h1>
  18. <input id="fileSelector" type="file" />
  19. <input id="submitBtn" type="submit" />
  20. <div id="msg"></div>
  21. <script>
  22. (function () {
  23. // 对更多字符编码的 url encode 格式
  24. const camSafeUrlEncode = function (str) {
  25. return encodeURIComponent(str)
  26. .replace(/!/g, '%21')
  27. .replace(/'/g, '%27')
  28. .replace(/\(/g, '%28')
  29. .replace(/\)/g, '%29')
  30. .replace(/\*/g, '%2A');
  31. };
  32. // 计算签名
  33. const getAuthorization = function (opt, callback) {
  34. // 替换为自己服务端地址 获取put上传签名
  35. const url = `http://127.0.0.1:3000/put-sign?ext=${opt.ext}`;
  36. const xhr = new XMLHttpRequest();
  37. xhr.open('GET', url, true);
  38. xhr.onload = function (e) {
  39. let credentials;
  40. try {
  41. const result = JSON.parse(e.target.responseText);
  42. credentials = result;
  43. } catch (e) {
  44. callback('获取签名出错');
  45. }
  46. if (credentials) {
  47. callback(null, {
  48. securityToken: credentials.securityToken,
  49. authorization: credentials.authorization,
  50. cosKey: credentials.cosKey,
  51. cosHost: credentials.cosHost,
  52. });
  53. } else {
  54. console.error(xhr.responseText);
  55. callback('获取签名出错');
  56. }
  57. };
  58. xhr.onerror = function (e) {
  59. callback('获取签名出错');
  60. };
  61. xhr.send();
  62. };
  63. // 上传文件
  64. const uploadFile = function (file, callback) {
  65. const fileName = file.name;
  66. let ext = '';
  67. const lastDotIndex = fileName.lastIndexOf('.');
  68. if (lastDotIndex > -1) {
  69. // 这里获取文件后缀 由服务端生成最终上传的路径
  70. ext = fileName.substring(lastDotIndex + 1);
  71. }
  72. getAuthorization({ ext }, function (err, info) {
  73. if (err) {
  74. alert(err);
  75. return;
  76. }
  77. const auth = info.authorization;
  78. const securityToken = info.securityToken;
  79. const Key = info.cosKey;
  80. const protocol =
  81. location.protocol === 'https:' ? 'https:' : 'http:';
  82. const prefix = protocol + '//' + info.cosHost;
  83. const url =
  84. prefix + '/' + camSafeUrlEncode(Key).replace(/%2F/g, '/');
  85. const xhr = new XMLHttpRequest();
  86. xhr.open('PUT', url, true);
  87. xhr.setRequestHeader('Authorization', auth);
  88. securityToken &&
  89. xhr.setRequestHeader('x-cos-security-token', securityToken);
  90. xhr.upload.onprogress = function (e) {
  91. console.log(
  92. '上传进度 ' +
  93. Math.round((e.loaded / e.total) * 10000) / 100 +
  94. '%'
  95. );
  96. };
  97. xhr.onload = function () {
  98. if (/^2\d\d$/.test('' + xhr.status)) {
  99. const ETag = xhr.getResponseHeader('etag');
  100. callback(null, { url: url, ETag: ETag });
  101. } else {
  102. callback('文件 ' + Key + ' 上传失败,状态码:' + xhr.status);
  103. }
  104. };
  105. xhr.onerror = function () {
  106. callback(
  107. '文件 ' + Key + ' 上传失败,请检查是否没配置 CORS 跨域规则'
  108. );
  109. };
  110. xhr.send(file);
  111. });
  112. };
  113. // 监听表单提交
  114. document.getElementById('submitBtn').onclick = function (e) {
  115. const file = document.getElementById('fileSelector').files[0];
  116. if (!file) {
  117. document.getElementById('msg').innerText = '未选择上传文件';
  118. return;
  119. }
  120. file &&
  121. uploadFile(file, function (err, data) {
  122. console.log(err || data);
  123. document.getElementById('msg').innerText = err
  124. ? err
  125. : '上传成功,ETag=' + data.ETag;
  126. });
  127. };
  128. })();
  129. </script>
  130. </body>
  131. </html>