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

如何通过NextJS API代理将图片上传至Azure Blob Storage

问题原因

你的代码存在两个核心问题导致图片上传后变成乱码:

  1. 前端手动设置了multipart/form-data请求头,丢失了浏览器自动生成的boundary参数,导致后端无法正确解析文件二进制数据。
  2. NextJS API路由默认不会解析multipart/form-data格式的请求,req.body会被处理成字符串而非原始二进制流,直接传给Azure Blob时自然会变成乱码。
解决方案

前端代码修改

移除手动设置的Content-type请求头,FormData提交时浏览器会自动生成包含boundary的正确请求头:

const [image, setImage] = useState({ preview: '', raw: '' })

const handleImageChange = (e) => {
  setImage({
    preview: URL.createObjectURL(e.target.files[0]),
    raw: e.target.files[0]
  })
}

// 上传逻辑
const uploadImage = async () => {
  if (!image.raw) return
  const picFile = new FormData()
  picFile.append("image", image.raw)
  const picOptions = {
    method: 'POST',
    // 移除手动设置的Content-type,浏览器会自动处理
    body: picFile,
  }

  const picResponse = await fetch(profilePicEndpoint, picOptions)
  const result = await picResponse.json()
  console.log(result)
}

return (
  <>
    <input accept=".png, .jpg, .jpeg" type="file" id="image-upload" style={{ display: 'none' }} onChange={handleImageChange} />
    <button onClick={uploadImage}>上传头像</button>
  </>
)

后端NextJS API路由修改

需要使用formidable库解析multipart/form-data请求,获取文件的二进制buffer后再上传到Azure Blob:

  1. 安装依赖:
npm install formidable
  1. 修改API路由代码:
import formidable from 'formidable'
import fs from 'fs/promises'

// 禁用NextJS默认的bodyParser,因为要手动解析multipart/form-data
export const config = {
  api: {
    bodyParser: false,
  },
}

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ message: '仅支持POST请求' })
  }

  // 解析FormData
  const form = formidable({})
  const [fields, files] = await form.parse(req)
  
  // 获取上传的文件对象
  const uploadedFile = files.image?.[0]
  if (!uploadedFile) {
    return res.status(400).json({ message: '未上传文件' })
  }

  // 动态生成Blob文件名(避免覆盖),使用原始文件名
  const blobFileName = uploadedFile.originalFilename
  const blobEndpoint = `https://STORAGEACCOUNT.blob.core.windows.net/MyContainerhere/${blobFileName}?BunchofCredentialsHere`

  // 读取文件的二进制buffer
  const fileBuffer = await fs.readFile(uploadedFile.filepath)

  // 上传到Azure Blob
  const blobOptions = {
    method: 'PUT',
    headers: {
      'x-ms-blob-type': 'BlockBlob',
      // 设置正确的Content-Type,用文件原始的MIME类型
      'Content-Type': uploadedFile.mimetype
    },
    body: fileBuffer,
  }

  const blobResponse = await fetch(blobEndpoint, blobOptions)
  if (!blobResponse.ok) {
    return res.status(500).json({ message: '上传到Azure失败' })
  }

  res.status(200).json({ 
    message: '上传成功,更新将在24小时内生效',
    blobUrl: blobEndpoint.split('?')[0] // 返回不带SAS的Blob地址
  })
}

关键说明

  • 禁用NextJS默认的bodyParser是必须的,否则formidable无法正确解析请求。
  • 必须设置Content-Type为文件原始的MIME类型,确保Azure Blob存储正确识别文件格式。
  • 动态设置Blob文件名,避免每次上传覆盖同一个文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 19:09:57