<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Ajax Put 涓婁紶锛堟湇鍔$璁$畻绛惧悕锛�</title>
    <style>
      h1,
      h2 {
        font-weight: normal;
      }

      #msg {
        margin-top: 10px;
      }
    </style>
  </head>
  <body>
    <h1>Ajax Put 涓婁紶锛堟湇鍔$璁$畻绛惧悕锛�</h1>

    <input id="fileSelector" type="file" />
    <input id="submitBtn" type="submit" />

    <div id="msg"></div>

    <script>
      (function () {
        // 瀵规洿澶氬瓧绗︾紪鐮佺殑 url encode 鏍煎紡
        const camSafeUrlEncode = function (str) {
          return encodeURIComponent(str)
            .replace(/!/g, '%21')
            .replace(/'/g, '%27')
            .replace(/\(/g, '%28')
            .replace(/\)/g, '%29')
            .replace(/\*/g, '%2A');
        };

        // 璁$畻绛惧悕
        const getAuthorization = function (opt, callback) {
          // 鏇挎崲涓鸿嚜宸辨湇鍔$鍦板潃 鑾峰彇put涓婁紶绛惧悕
          const url = `http://127.0.0.1:3000/put-sign?ext=${opt.ext}`;
          const xhr = new XMLHttpRequest();
          xhr.open('GET', url, true);
          xhr.onload = function (e) {
            let credentials;
            try {
              const result = JSON.parse(e.target.responseText);
              credentials = result;
            } catch (e) {
              callback('鑾峰彇绛惧悕鍑洪敊');
            }
            if (credentials) {
              callback(null, {
                securityToken: credentials.securityToken,
                authorization: credentials.authorization,
                cosKey: credentials.cosKey,
                cosHost: credentials.cosHost,
              });
            } else {
              console.error(xhr.responseText);
              callback('鑾峰彇绛惧悕鍑洪敊');
            }
          };
          xhr.onerror = function (e) {
            callback('鑾峰彇绛惧悕鍑洪敊');
          };
          xhr.send();
        };

        // 涓婁紶鏂囦欢
        const uploadFile = function (file, callback) {
          const fileName = file.name;
          let ext = '';
          const lastDotIndex = fileName.lastIndexOf('.');
          if (lastDotIndex > -1) {
            // 杩欓噷鑾峰彇鏂囦欢鍚庣紑 鐢辨湇鍔$鐢熸垚鏈€缁堜笂浼犵殑璺緞
            ext = fileName.substring(lastDotIndex + 1);
          }
          getAuthorization({ ext }, function (err, info) {
            if (err) {
              alert(err);
              return;
            }
            const auth = info.authorization;
            const securityToken = info.securityToken;
            const Key = info.cosKey;
            const protocol =
              location.protocol === 'https:' ? 'https:' : 'http:';
            const prefix = protocol + '//' + info.cosHost;
            const url =
              prefix + '/' + camSafeUrlEncode(Key).replace(/%2F/g, '/');
            const xhr = new XMLHttpRequest();
            xhr.open('PUT', url, true);
            xhr.setRequestHeader('Authorization', auth);
            securityToken &&
              xhr.setRequestHeader('x-cos-security-token', securityToken);
            xhr.upload.onprogress = function (e) {
              console.log(
                '涓婁紶杩涘害 ' +
                  Math.round((e.loaded / e.total) * 10000) / 100 +
                  '%'
              );
            };
            xhr.onload = function () {
              if (/^2\d\d$/.test('' + xhr.status)) {
                const ETag = xhr.getResponseHeader('etag');
                callback(null, { url: url, ETag: ETag });
              } else {
                callback('鏂囦欢 ' + Key + ' 涓婁紶澶辫触锛岀姸鎬佺爜锛�' + xhr.status);
              }
            };
            xhr.onerror = function () {
              callback(
                '鏂囦欢 ' + Key + ' 涓婁紶澶辫触锛岃妫€鏌ユ槸鍚︽病閰嶇疆 CORS 璺ㄥ煙瑙勫垯'
              );
            };
            xhr.send(file);
          });
        };

        // 鐩戝惉琛ㄥ崟鎻愪氦
        document.getElementById('submitBtn').onclick = function (e) {
          const file = document.getElementById('fileSelector').files[0];
          if (!file) {
            document.getElementById('msg').innerText = '鏈€夋嫨涓婁紶鏂囦欢';
            return;
          }
          file &&
            uploadFile(file, function (err, data) {
              console.log(err || data);
              document.getElementById('msg').innerText = err
                ? err
                : '涓婁紶鎴愬姛锛孍Tag=' + data.ETag;
            });
        };
      })();
    </script>
  </body>
</html>