我试图让用户上传视频文件并通过我的NextJS api发送到我的Express后端(并将其存储在S3桶中,我不需要将其保存在我的服务器上),但经过几天的搜索,无法弄清楚如何做到这一点。我知道NextJS有一个限制,它不能读取多部分表单数据,但我不明白如何战略性地解决这个问题。我已经看到了像multer
和formidable
的包,但我不确定如何使用它们(因为它们似乎是为后端,我有麻烦将文件传递给我的前端API)。
由于视频文件可能很大,我认为我需要从前端直接将视频文件上传到s3(使用多部分上传),然后将视频的AWS URL发送到后端。如果这是正确的方法,我该怎么做?
项目设置:NextJS前端运行在port 3000
+ Express后端服务器运行在port 5000
。下面是我的代码:
很常见。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"
>