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
相关产品推荐
相关产品推荐

