Next.js Server Actions上传大文件到S3报错,如何实现流式上传?
解决Next.js Server Actions上传文件到S3的FileLike类型错误
你遇到的错误是因为Next.js Server Actions中从FormData获取的File是FileLike对象,而AWS SDK v2的putObject方法不支持直接传入这种类型,它只接受字符串、Buffer或者Node.js可读流。下面是不用第三方包的流式上传解决方案:
核心解决思路
把Web标准的FileLike对象转换成Node.js可读流,直接作为S3上传的Body,实现流式上传(避免大文件占满内存)。
修改后的代码
// 导入所需包(比如aws-sdk的S3) import { S3 } from 'aws-sdk'; async function createEntry(formData) { "use server"; // 先执行数据库写入逻辑... const file = formData.get("avatar"); if (!file) throw new Error("未选择文件"); // 1. 将FileLike转成Node.js可读流 const webStream = file.stream(); // 把Web ReadableStream转换为Node.js Readable流 const nodeStream = require('stream').Readable.from(webStream); const s3 = new S3({ accessKeyId: 'xxx', secretAccessKey: 'xxx', region: 'xxx', }); const params = { Bucket: 'xxx', Key: `uploads/${Date.now()}-${file.name}`, // 自定义文件路径/名称 Body: nodeStream, ContentType: file.type // 必须设置正确的文件类型,否则S3会默认存为binary/octet-stream }; try { await s3.putObject(params).promise(); console.log(`文件 ${file.name} 上传成功`); } catch (err) { console.error('上传失败:', err); throw err; } } export default async function UploadPage() { return ( <> <form action={createEntry}> {/* 其他表单字段 */} <label> 选择图片 <input type="file" name="avatar" accept="image/png, image/jpeg" /> </label> <input type="submit" value="上传图片" /> </form> </> ); }
关键说明
file.stream():Next.js的FileLike对象支持Web API的stream()方法,返回Web标准的ReadableStream。stream.Readable.from(webStream):Node.js内置的stream模块可以把Web ReadableStream转换成Node.js可读流,这一步不需要额外第三方包。ContentType:必须手动设置,否则S3会把文件识别为binary/octet-stream,导致下载或预览时出现问题。
这样修改后,就能实现流式上传大文件到S3,同时避免类型错误。
内容的提问来源于stack exchange,提问作者danish
相关产品推荐
相关产品推荐

