我有一个Django服务器和react前端应用程序。我有一个同时接收数据和文件对象的端点。 api客户端的javascript版本工作正常,看起来像这样。
const address = `${baseAddress}/${endpoint}`;
const multipartOptions = {
headers: {
'Content-Type': 'multipart/form-data',
'Content-Disposition': `attachment; filename=${filename}`,
'X-CSRFToken': getCSRFToken(),
},
};
const formData = new FormData();
formData.append('file', file);
const json = JSON.stringify(metadata);
const blob = new Blob([json], {
type: 'application/json',
});
formData.append('metadata', blob);
return axios.post(address, formData, multipartOptions);
如您所见,我正在使用Blob将元数据添加到表单数据中并将其传递到服务器。
在服务器上打印request.data
可以得到类似的信息。
<QueryDict: {'file': [<InMemoryUploadedFile: admin_12183.zip (application/zip)>], 'metadata': [<InMemoryUploadedFile: blob (application/json)>]}>
因此,我可以在django服务器上同时访问request.data.get('file')
和request.data.get('metadata')
。
现在我必须在python
中做类似的事情。我尝试使用requests
使内容正确,但是在QueryDict
中没有得到两个单独的键。 python代码如下所示。
with open("file.zip", "rb") as fp:
with open("metadata.json", "rb") as meta:
file_headers = {
**headers,
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryjzAXwA7GGcenPlPk',
}
data = {
"file": "",
}
files = {
'file': ("file.zip", fp, "application/zip"),
'metadata': ("blob", meta, "application/json"),
}
response = requests.post(f"{BASE_URL}/api/endpoint", data=data, files=files, headers=file_headers)
print(response.status_code)
如果我不同时发送文件和数据,则request.data
中什么也不会发送。而且,如果我同时发送这两个数据,那么我将在单个密钥中获取两个数据,这与我在data
变量中拥有的密钥相对应。
服务器中包含此代码
def post(self, request, *args, **kwargs):
file_obj = request.data.get('file')
metadata = request.data.get('metadata')
# both are empty if either one of files or data is not sent from the client
# if both are sent, then request.data has only one key, with everything inside of it
# works fine with the javascript code
我认为我缺少一些很小而琐碎的东西。 请帮忙。
答案 0 :(得分:0)
结果是我在标题中添加了内容类型,这就是导致所有问题的原因。工作代码如下:
file_headers = {
**headers,
# make sure there is no content type in the header
}
files = {
'file': ("file.zip", shape, "application/zip"),
'metadata': ("blob", meta, "application/json"),
}
response = requests.post(f"{BASE_URL}/api/shapefiles", files=files, headers=file_headers)
print(response.text, response.status_code)