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

Next.js 13与Azure Blob Storage的CORS问题求助

解决Next.js 13上传Azure Blob Storage的CORS问题(无需/api文件夹)

问题根源

你当前的代码是客户端组件(使用了useForm这类客户端Hook),直接在浏览器中向Azure Blob Storage发起请求,触发了浏览器的CORS策略限制。要解决这个问题,必须把上传逻辑移到服务器端执行——利用Next.js 13的Server Action特性,不用创建/api文件夹就能实现服务器端处理。

具体解决方案

1. 启用Server Action

在next.config.js中添加配置开启Server Action:

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverActions: true,
  },
}

module.exports = nextConfig

2. 拆分代码:客户端做UI,服务器端处理上传

把上传逻辑抽成Server Action函数,客户端只负责收集文件并调用这个函数:

客户端组件(负责UI交互):

'use client'
import { useForm } from 'react-hook-form'
import { uploadToAzureBlob } from './upload-action'

export default function UploaderOneImage() {
  const { register, handleSubmit } = useForm()

  const onSubmit = async (formData: { files: File[] }) => {
    if (!formData.files[0]) return
    try {
      await uploadToAzureBlob(formData.files[0])
      console.log('文件上传成功')
    } catch (err) {
      console.error('上传失败:', err)
    }
  }

  return (
    <>
      <h2>Upload</h2>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input type='file' {...register('files', { required: true })} />
        <button type='submit'>Save!</button>
      </form>
    </>
  )
}

Server Action函数(服务器端执行):
新建upload-action.ts文件,添加'use server'标记为服务器端函数:

'use server'
import { BlobServiceClient } from '@azure/storage-blob'
import nanoId from '@/utils/nanoId'

export async function uploadToAzureBlob(file: File) {
  // 生成新文件名
  const newFileName = nanoId() + '.' + file.name.split('.').pop()

  // 建议将配置存入环境变量,避免硬编码
  const account = process.env.AZURE_STORAGE_ACCOUNT || 'serlismaldonado'
  const sas = process.env.AZURE_STORAGE_SAS || 'SASEXAMPLE'
  const containerName = process.env.AZURE_STORAGE_CONTAINER || 'diagnostics'

  // 正确初始化BlobServiceClient(SAS令牌需拼在URL后)
  const blobServiceClient = new BlobServiceClient(
    `https://${account}.blob.core.windows.net/?${sas}`
  )

  const containerClient = blobServiceClient.getContainerClient(containerName)
  const blobClient = containerClient.getBlockBlobClient(newFileName)

  // 将前端文件转换为服务器端可处理的Buffer
  const arrayBuffer = await file.arrayBuffer()
  const buffer = Buffer.from(arrayBuffer)

  const uploadOptions = {
    blobHTTPHeaders: {
      blobContentType: file.type,
    },
  }

  // 执行上传操作
  await blobClient.uploadData(buffer, uploadOptions)
}

3. 关键注意事项

  • SAS令牌权限:确保你的Azure SAS令牌拥有Write权限,否则服务器端无法完成上传。
  • 环境变量安全:将Azure账号、SAS令牌、容器名存入.env.local文件:
    AZURE_STORAGE_ACCOUNT=serlismaldonado
    AZURE_STORAGE_SAS=你的实际SAS令牌
    AZURE_STORAGE_CONTAINER=diagnostics
    
  • Next.js版本要求:必须使用13.4及以上版本,Server Action是App Router专属特性,Pages Router不支持。

原理说明

Server Action在你的Next.js服务器上执行上传请求,而非从用户浏览器直接发往Azure,完全绕开了浏览器的CORS限制,因此不会出现CORS错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:23:27