element plus upload http-request 手动上传 Minio

<el-upload
            method="put"
            :before-upload="beforeAvatarUpload"
            :on-error="handleError"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemove"
            on-success="handlePictureCardSuccess"
            action="#"
            list-type="picture-card"
            :http-request="handleUpload"
            :file-list="fileList"
          >
            <el-icon>
              <plus />
            </el-icon>
          </el-upload>

const handleUpload = async ({ file, onProgress, onSuccess, onError }: { file: File; onProgress: Function; onSuccess: Function; onError: Function }) => {
  try {
    // 1. 获取上传地址
    const uploadUrlResponse = await api.post('你的签名URL接口')
    const uploadUrl = uploadUrlResponse.data
    // 2. 创建 FormData 对象并添加文件
    const formData = new FormData()
    formData.append('file', file)
    // 3. 使用 axios 上传文件
    const response = await axios.put(uploadUrl, file, {
      // headers: {
      //   'Content-Type': 'multipart/form-data',
      // },
      // 进度条,你可以选择不需要  
      onUploadProgress: (progressEvent: ProgressEvent) => {
        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        uploadPercentage.value = percentCompleted
        if (onProgress) {
          onProgress({ percent: percentCompleted })
        }
      },
    })
    console.log('🚀 ~ handleUpload ~ response:', response)
    if (response.status === 200) {
      ElMessage.success({
        message: '上传成功',
        type: 'success',
      })
      if (onSuccess) {
        onSuccess(response.data) // 上传成功时的回调
        // 添加文件到 fileList 以便预览
        fileList.value.push({
          name: file.name,
          url: URL.createObjectURL(file),
        })
      }
    } else {
      ElMessage.error('上传失败')
    }
  } catch (error) {
    // 上传失败后的回调
    // if (onError) {
    //   onError(error)
    // }
  }
}

关于上传文件的数据格式

在文件上传过程中,上传的数据需要以一种能够被服务器处理的格式传输。上传文件通常有两种常见方式:

  1. 使用 FormData 对象:这种方式适用于 POST 请求,通常用于多部分表单数据上传。这种方式可以轻松地上传多个文件和其他表单数据。
  2. 直接上传文件的二进制数据:这种方式适用于 PUT 请求或 POST 请求,直接上传文件的内容,而不是表单数据。这种方式适用于你已经有一个特定的上传URL,并且只需要上传文件内容。

在上面示例中,文件是通过 PUT 请求上传的,并且上传的数据是文件的二进制数据。下面是详细解释和示例:

使用 FormData 上传文件

FormData 对象允许你构建包含文件和其他数据的多部分表单数据,然后可以使用 axios.post 进行上传:

const formData = new FormData();
formData.append('file', file);
const response = await axios.post(uploadUrl, formData, {
  headers: {
    'Content-Type': 'multipart/form-data',
  }
});

直接上传文件的二进制数据

在最开头的的示例中,文件是通过 PUT 请求直接上传的,上传的是文件的二进制数据。这种方式适用于你已经有一个预签名的URL或专用的文件上传接口:

为什么使用二进制数据

  1. 效率:上传文件的二进制数据可以避免将文件数据嵌入到多部分表单结构中,可能会更高效,特别是对于大文件上传。
  2. 简单性:对于一些云存储服务(如AWS S3)的预签名URL上传,你只需要将文件的二进制数据上传到指定的URL,无需处理表单数据格式。
  3. 灵活性:某些专用的文件上传接口可能要求直接上传二进制数据,而不是多部分表单数据。

关于Minio

Minio 是一个高性能的对象存储服务器,兼容 Amazon S3 云存储服务的 API。它是一个开源项目,旨在提供一个可以在任何基础设施上部署的私有云存储解决方案。Minio 被广泛应用于构建高可用性、高性能的数据存储环境,特别适用于大数据和机器学习等需要处理大量数据的应用场景。

以下是 Minio 的一些主要特点:

  1. 兼容性:Minio 完全兼容 Amazon S3 API,这意味着使用者可以使用现有的 S3 客户端工具和库与 Minio 进行交互。
  2. 高性能:Minio 设计用于高性能需求,支持高达每秒几百 GB 的吞吐量。
  3. 简易性:Minio 安装和配置非常简单,只需几分钟即可设置完成,适合开发者和系统管理员快速部署。
  4. 扩展性:Minio 可以横向扩展,适应从小规模到企业级的存储需求。
  5. 安全性:Minio 支持端到端加密和标准的访问控制列表(ACL)管理,保障数据安全。
  6. 多平台支持:Minio 可以运行在多个操作系统上,包括 Linux、Windows 和 macOS,同时也可以在 Docker 容器中运行。

使用 Minio,企业和开发者可以在本地数据中心或云环境中搭建一个与 S3 API 兼容的对象存储服务,享受灵活的部署方式和低成本的存储解决方案。

后端服务:我们创建了一个 Node.js 服务,它使用 Minio 客户端生成签名 URL。前端会调用这个服务来获取上传文件所需的 URL。

前端代码:我们使用 Vue 3 和 axios 来实现文件上传逻辑。用户选择文件后,前端会请求签名 URL,然后使用这个 URL 上传文件。

更多推荐