如何在SvelteKit POST动作中获取可用File对象?(解决byteLength报错)
解决SvelteKit Server Action中Firebase文件上传报错问题
问题根源
在SvelteKit的+page.server.ts中,通过request.formData()获取的File对象是Node.js环境下的File实现(属于@types/node类型定义),和浏览器原生的File/Blob对象结构不兼容。Firebase的uploadBytes方法仅识别浏览器环境的Blob/File,或是Node.js的Buffer/可读流,因此直接传入Node.js File会抛出Cannot read properties of undefined (reading 'byteLength')错误。
可行解决方案
方案1:将Node.js File转为Buffer(推荐)
读取文件内容为Buffer后再传给Firebase,适配性更强:
修正后的+page.server.ts代码:
import { ref, uploadBytes } from "firebase/storage"; import { storage } from '$lib/firebase'; // 替换为你的Firebase存储实例路径 export const actions = { uploadPDF: async ({ request }) => { const data = await request.formData(); const file = data.get('path') as File; if (file) { // 将Node.js File转换为Buffer const buffer = Buffer.from(await file.arrayBuffer()); // 替换为你的实际路径变量 const yearFrom = "2024"; const seasonFrom = "winter"; const uploadRef = ref(storage, `Vereinsblatt/soli_info_${yearFrom}_${seasonFrom}.pdf`); // 执行上传 await uploadBytes(uploadRef, buffer); } return { success: true }; }, } satisfies Actions;
方案2:转为可读流(大文件场景更高效)
如果上传大文件,用Node.js可读流可以避免内存占用过高:
import { ref, uploadBytes } from "firebase/storage"; import { storage } from '$lib/firebase'; import { createReadStream } from 'fs'; export const actions = { uploadPDF: async ({ request }) => { const data = await request.formData(); const file = data.get('path') as File; if (file) { // 利用Node.js File的path属性创建可读流 const stream = createReadStream(file.path); const uploadRef = ref(storage, `Vereinsblatt/soli_info_${yearFrom}_${seasonFrom}.pdf`); await uploadBytes(uploadRef, stream); } return { success: true }; }, } satisfies Actions;
补充说明
- 前端直接通过
event.target[0].files[0]获取的是浏览器原生File对象,完全符合Firebase的参数要求,因此可以正常上传。 - 不要尝试用
new File([file], "xxx.pdf")这类方式转换,Node.js File无法直接转为浏览器环境的File对象,只会导致内容异常。
内容的提问来源于stack exchange,提问作者Peybro
相关产品推荐
相关产品推荐

