使用文件和数据将多部分表单数据从python传递到django服务器

时间:2020-06-23 17:27:01

标签: javascript python django python-requests

我有一个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
      

我认为我缺少一些很小而琐碎的东西。 请帮忙。

1 个答案:

答案 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)