完整教程:AWS 亚马逊 S3存储桶直传 前端demo 复制即可使用

自己踩过坑不想别人也踩坑了 亚马逊S3存储桶直传前端demo复制即可使用

<!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>S3 直传示例</title>
      <style>
        .container {
        max-width: 600px;
        margin: 50px auto;
        padding: 20px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.1)
        ;
        border-radius: 8px;
        }
        .upload-area {
        border: 2px dashed #ccc;
        padding: 20px;
        text-align: center;
        margin: 20px 0;
        border-radius: 4px;
        }
        .upload-area.dragover {
        background-color: #e1f5fe;
        border-color: #2196f3;
        }
        .progress {
        margin-top: 20px;
        display: none;
        }
        .progress-bar {
        height: 20px;
        background-color: #4caf50;
        width: 0%;
        transition: width 0.3s;
        }
        .status {
        margin-top: 10px;
        color: #666;
        }
      </style>
    </head>
    <body>
        <div class="container">
      <h1>S3 直传示例</h1>
          <div class="upload-area" id="dropZone">
        <p>拖拽文件到这里或点击选择文件</p>
          <input type="file" id="fileInput" style="display: none" />
            <button onclick="document.getElementById('fileInput'
          ).click(
        )">选择文件</button>
      </div>
        <div class="progress" id="progressContainer">
      <div class="progress-bar" id="progressBar"></div>
      <div class="status" id="status"></div>
      </div>
    </div>
    <script>
      const dropZone = document.getElementById("dropZone"
      )
      ;
      const fileInput = document.getElementById("fileInput"
      )
      ;
      const progressContainer = document.getElementById("progressContainer"
      )
      ;
      const progressBar = document.getElementById("progressBar"
      )
      ;
      const status = document.getElementById("status"
      )
      ;
      // 处理拖拽事件
      ["dragenter"
      , "dragover"
      , "dragleave"
      , "drop"].forEach((eventName
      ) =>
      {
      dropZone.addEventListener(eventName, preventDefaults, false
      )
      ;
      }
      )
      ;
      function preventDefaults(e
      ) {
      e.preventDefault(
      )
      ;
      e.stopPropagation(
      )
      ;
      }
      ["dragenter"
      , "dragover"].forEach((eventName
      ) =>
      {
      dropZone.addEventListener(eventName, highlight, false
      )
      ;
      }
      )
      ;
      ["dragleave"
      , "drop"].forEach((eventName
      ) =>
      {
      dropZone.addEventListener(eventName, unhighlight, false
      )
      ;
      }
      )
      ;
      function highlight(e
      ) {
      dropZone.classList.add("dragover"
      )
      ;
      }
      function unhighlight(e
      ) {
      dropZone.classList.remove("dragover"
      )
      ;
      }
      dropZone.addEventListener("drop"
      , handleDrop, false
      )
      ;
      fileInput.addEventListener("change"
      , handleFileSelect, false
      )
      ;
      function handleDrop(e
      ) {
      const dt = e.dataTransfer;
      const files = dt.files;
      handleFiles(files)
      ;
      }
      function handleFileSelect(e
      ) {
      const files = e.target.files;
      handleFiles(files)
      ;
      }
      async
      function handleFiles(files
      ) {
      const file = files[0]
      ;
      if (!file)
      return
      ;
      try {
      // 获取上传配置
      const response =
      await fetch(`BASEURL?file_name=${file.name
      }`
      )
      ;
      const data =
      await response.json(
      )
      ;
      if (data.code === 20000
      ) {
      // 显示进度条
      progressContainer.style.display = "block"
      ;
      progressBar.style.width = "0%"
      ;
      status.textContent = "开始上传..."
      ;
      // 执行上传
      const xhr =
      new XMLHttpRequest(
      )
      ;
      xhr.upload.onprogress = (e
      ) =>
      {
      if (e.lengthComputable) {
      const percentComplete = (e.loaded / e.total) * 100
      ;
      progressBar.style.width = percentComplete + "%"
      ;
      status.textContent = `上传进度: ${Math.round(percentComplete)
      }%`
      ;
      }
      }
      ;
      xhr.onload = (
      ) =>
      {
      if (xhr.status === 200
      ) {
      status.textContent = "上传成功!"
      ;
      status.style.color = "#4CAF50"
      ;
      }
      else {
      status.textContent = "上传失败,请重试"
      ;
      status.style.color = "#f44336"
      ;
      }
      }
      ;
      xhr.onerror = (
      ) =>
      {
      status.textContent = "上传出错,请重试"
      ;
      status.style.color = "#f44336"
      ;
      }
      ;
      xhr.open(data.data.method, data.data.url)
      ;
      xhr.send(file)
      ;
      }
      else {
      throw
      new Error(data.msg || "获取上传配置失败"
      )
      ;
      }
      }
      catch (error) {
      console.error("上传出错:"
      , error)
      ;
      status.textContent = "上传出错: " + error.message;
      status.style.color = "#f44336"
      ;
      }
      }
    </script>
  </body>
</html>
posted @ 2025-07-21 11:07  yfceshi  阅读(37)  评论(0)    收藏  举报