AWS 亚马逊 S3存储桶直传 前端demo 复制即可使用

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

html 复制代码
<!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>
相关推荐
尾善爱看海4 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
驳是4 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea4 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持5 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者5 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn5 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
计算机魔术师7 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端
计算机魔术师7 小时前
OpenAI的AI代理偷偷给RubyGems下毒,我们却毫无察觉
前端
甲维斯7 小时前
0代码,0建模,3句话开发一个3D游戏!
前端·游戏·游戏开发
IT_陈寒8 小时前
Vue的响应式更新把我坑惨了,原来问题出在这
前端·人工智能·后端