我正在尝试使用 django 构建一个 API,它支持将文件作为数组的数组上传。我想要实现的一个例子是,
[
{
"string": "Some string",
"files": [
"<uploaded file object 1>",
"<uploaded file object 2>"
]
},
{
"string": "Some string",
"files": [
"<uploaded file object 3>"
]
},
{
"string": "Some string",
"files": []
}
]
我不想为此使用base64编码的文件,因为文件有时可能很大,所以我不想增加使用base64的开销。
**我如何以最有效的方式实现此 API 调用,以及调用此 API 的最合适的结构是什么,并帮助一些 javascript 前端代码做到这一点。 **
我尝试将其移至 FormData,在那里我可以实现上面的上传,如下所示,但我无法从前端调用 API,它不起作用可能是因为我编写了错误的代码。
strings: ["Some string", "Some string", "Some string"]
files: [["<uploaded file object 1>", "<uploaded file object 2>"], ["<uploaded file object 3>"]]
对于我的后端,我使用 django(rest 框架),如果需要,这里是序列化器的相关部分
class StringSerializer(serializers.Serializer):
serializers = serializers.ListField(child=serializers.CharField())
files = serializers.ListField(
child=serializers.ListField(child=serializers.FileField()),
write_only=True,
required=False,
allow_empty=True,
default=[],
)
使用formData、前端和后端的示例代码(express)
前端编码亮点:
a. blob 对象已被创建来构想文件内容。 参考声明:stmt-1。
b.属性字符串已用于设置 formData 对象中的键。
c.数组中的每个 blob 对象都已单独添加到 formData 中。
以上两点,参考声明:stmt-2。
d。该 API 已在钩子 useEffect 内调用。 参考声明:stmt-3。
e。上传状态已更新为状态变量。 参考声明:stmt-4。
App.js
import { useEffect, useState } from 'react';
export default function App() {
const [uploadStatus, setUploadStatus] = useState('');
const someContent = '<q id="a"><span id="b">hey!</span></q>';
const blob = new Blob([someContent], { type: 'text/xml' }); // stmt 1
const data = [
{
string: 'Somestring1',
files: [blob, blob],
},
{
string: 'Somestring2',
files: [blob],
},
{
string: 'Somestring3',
files: [blob],
},
];
const formData = new FormData();
data.forEach((rec) => {
rec.files.forEach((file) => {
formData.append(rec.string, file); // stmt-2
});
});
useEffect(() => {
fetch('http://localhost:3001/api/upload', {
method: 'POST',
body: formData,
})
.then((response) => response.text())
.then((data) => setUploadStatus(data)); // stmt-4
}, []); // stmt-3
return 'Upload Status : ' + (uploadStatus ? uploadStatus : 'Unknown');
}
后端 - 使用 multer 进行表达
编码亮点
a.前端代码中的multipart-formdata已被nodejs中间件multer接收。有关 multer 的更多信息,请参阅页面 https://www.npmjs.com/package/multer。
服务器.js
const express = require('express');
const multer = require('multer');
const cors = require('cors');
const upload = multer({
dest: 'uploads',
});
const app = express();
app.use(cors());
app.post('/api/upload', upload.any(), (req, res, next) => {
console.log(req.files);
res.send('success');
});
app.listen(3001, () => {
console.log('Listening...');
});
试运行:
运行前端代码,文件将被上传,并且在后端服务器上,将创建服务器控制台日志,如下所示。
[
{
fieldname: 'Somestring1',
originalname: 'blob',
encoding: '7bit',
mimetype: 'text/xml',
destination: 'uploads',
filename: 'f94460f91f497bac0c1e0fdc4292eadc',
path: 'uploads/f94460f91f497bac0c1e0fdc4292eadc',
size: 38
},
{
fieldname: 'Somestring1',
originalname: 'blob',
encoding: '7bit',
mimetype: 'text/xml',
destination: 'uploads',
filename: 'deb237a854b4027a9e106effc236343d',
path: 'uploads/deb237a854b4027a9e106effc236343d',
size: 38
},
{
fieldname: 'Somestring2',
originalname: 'blob',
encoding: '7bit',
mimetype: 'text/xml',
destination: 'uploads',
filename: '52fd4e96f278f216f339be0f72ce1b6f',
path: 'uploads/52fd4e96f278f216f339be0f72ce1b6f',
size: 38
},
{
fieldname: 'Somestring3',
originalname: 'blob',
encoding: '7bit',
mimetype: 'text/xml',
destination: 'uploads',
filename: '781e6d3bbf3fb01149fa7fd8e428339d',
path: 'uploads/781e6d3bbf3fb01149fa7fd8e428339d',
size: 38
}
]
后台的uploads文件夹里会有上传的文件。其列表已附在下面。