我试图让用户上传视频文件并通过我的 NextJS api 将其发送到我的 Express 后端(并将其存储在 S3 存储桶中,我不需要将其保存在我的服务器上),但不能经过几天的搜索找出如何做。我知道 NextJS 有一个限制,它无法读取多部分表单数据,但我不明白如何从策略上解决这个问题。我见过像
multer
和 formidable
这样的包,但我不确定如何使用它们(因为它们似乎是用于后端的,而且我在将文件传递到前端 API 时遇到了麻烦)。
由于视频文件可能很大,我认为我需要将视频文件直接从前端上传到 s3(使用分段上传),然后将视频的 AWS URL 发送到后端。如果这是正确的方法,我该怎么做?
项目设置:NextJS 前端在
port 3000
上运行 + Express 后端服务器在 port 5000
上运行。 这是我的代码:
FileUpload.tsx(前端)
...
<div>
<div>
{
previewURL != null ?
file.type.includes("video") ?
<video id="video" width="800" controls>
<source src={ previewURL } id="videoSrc" />
</video>
:
<audio id="audio" controls>
<source src={ previewURL } id="audioSrc" />
</audio>
: null
}
<form action="/api/uploadToAssemblyAi" method="post">
<label htmlFor="file">File</label>
<input
type="file"
id="file"
name="file"
onChange={ generatePreview }
/>
<button type="submit"> Upload </button>
<button type="reset" onChange={ clearFile }> Clear </button>
</form>
</div>
</div>
...
/api/uploadToAssemblyAi.tsx(前端)
import type { NextApiRequest, NextApiResponse } from 'next'
import axios from "axios"
export const config = {
api: {
bodyParser: false
}
}
export async function uploadData(file: File) {
// Prep to send file to backend
const BACKEND_API_URL = process.env.BACKEND_URL
const assembly = axios.create({
baseURL: BACKEND_API_URL,
withCredentials: true,
});
// Add file to request
let formData = new FormData();
formData.append("file", file);
// Call backend
const { data } = await assembly.post(`${BACKEND_API_URL}/api/synthesize/transcribe}`, formData)
const transcriptionId = data.transcriptionId
return transcriptionId
}
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const file = req.body.file
// ^^^ This is not working, I cannot access the file from the form (this is for communication purposes, I know this isn't the right way to do it)
try {
const transcriptionId = await uploadData(file)
return res.status(201).redirect(307, `/calls/${transcriptionId}`)
} catch (err) {
console.log("Error: " + err)
return res.status(400).send( { msg: err })
}
}
uploadController.ts(后端)
...
// This is where I want to receive the file to upload to AWS
export async function transcribeController(req: Request, res: Response) {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send({ msg: 'No files were uploaded.' });
}
const file = req.files
const file = req.body
// ^^^ I'm not sure how to access the file on the backend since I cannot even send it from the frontend (this is for communication purposes, I know this isn't the right way to do it)
return
}
...
您可以使用
FormData
发送请求。这将作为 multipart/form-data
请求发送。
let formData = new FormData();
formData.append('file', file);
const response = await fetch('/api/uploadToAssemblyAi', {
method: 'POST',
body: formData,
});
您还可以更新
form
元素以指定该内容类型:
<form
action="/api/uploadToAssemblyAi"
method="post"
enctype="multipart/form-data"
>
当我在 node.js 服务器上获取表单时,它给了我意外的表单结束错误,我使用它创建了表单
let formData = new FormData(); formData.append('文件', 文件);
const 响应 = 等待 fetch('/api/uploadToAssemblyAi', { 方法:'POST', 正文:表单数据, });