You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Vue.js实现多张图片上传至Amazon S3?解决重复上传问题

Vue.js 多图片上传至Amazon S3 问题解决方案

问题分析

  • 前端:两个文件选择框绑定的方法将选中文件赋值给同一个selectedFile变量,导致后选文件覆盖前选文件;文件名也共用一个变量,无法分别显示。
  • 后端:使用upload.single("photo")仅支持单文件上传,无法处理多文件请求。

前端代码修改

1. 调整数据定义

将单个文件变量改为数组,用于存储多个选中文件及对应文件名:

data() {
  return {
    selectedFiles: [], // 存储选中的多个文件
    fileNames: [] // 存储对应文件名
  }
}

2. 修改模板结构

为每个文件输入框添加索引标识,绑定统一的文件选择方法,并分别显示对应文件名:

<label class="choosefile-button">
  <input
    type="file"
    @change="(e) => onFileSelected(0, e)"
  >
  <p style="margin-top: -70px">{{ fileNames[0] || '未选择文件' }}</p>
</label>

<label class="choosefile-button">
  <input
    type="file"
    @change="(e) => onFileSelected(1, e)"
  >
  <p style="margin-top: -70px">{{ fileNames[1] || '未选择文件' }}</p>
</label>

3. 统一文件选择方法

通过索引区分不同输入框,将选中文件和文件名存入对应数组位置,并新增上传方法:

methods: {
  onFileSelected(index, event) {
    const file = event.target.files[0];
    this.selectedFiles[index] = file;
    this.fileNames[index] = file ? file.name : '';
  },
  async uploadFiles() {
    const formData = new FormData();
    // 遍历选中文件,添加到FormData
    this.selectedFiles.forEach((file, index) => {
      if (file) {
        formData.append(`photo${index + 1}`, file);
      }
    });

    // 发送POST请求到后端
    try {
      await axios.post('/products', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      });
      alert('上传成功');
      // 重置选择状态
      this.selectedFiles = [];
      this.fileNames = [];
    } catch (error) {
      console.error('上传失败:', error);
      alert('上传失败,请重试');
    }
  }
}

后端代码修改

1. 调整路由上传中间件

使用upload.fields()指定接收多个文件字段(对应前端的photo1和photo2):

router.post(`/products`, upload.fields([
  { name: 'photo1', maxCount: 1 },
  { name: 'photo2', maxCount: 1 }
]), async (req, res) => {
  try {
    // 收集两张图片的S3访问地址
    const photoUrls = [];
    if (req.files.photo1) photoUrls.push(req.files.photo1[0].location);
    if (req.files.photo2) photoUrls.push(req.files.photo2[0].location);

    let product = new Product();
    product.photos = photoUrls; // 假设Product模型的photos字段为数组类型
    await product.save();

    res.status(200).json({ message: '上传成功', product });
  } catch (error) {
    console.log(error);
    res.status(500).json({ message: '上传失败', error });
  }
});

2. (可选)优化S3文件命名

为避免文件名重复,可在中间件的key函数中加入字段名和随机字符串:

key: (req, file, cb) => {
  const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
  cb(null, `${file.fieldname}-${uniqueSuffix}`);
}

内容的提问来源于stack exchange,提问作者xander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 06:36:27