【问题标题】:How can I send multipart/form-data that contains json object and image file via curl? And how can I treat it with Django Rest Framework?如何通过 curl 发送包含 json 对象和图像文件的 multipart/form-data?以及如何使用 Django Rest Framework 来处理它?
【发布时间】:2014-07-16 18:44:17
【问题描述】:

例如,我通过终端尝试了该命令:

curl -F "profileImage=@/home/user/image.jpg" -F "{'firstName':'hello'};type=application/json" http://127.0.0.1:8000/api/v1/signup/

然后我收到了这样的request 对象:

print request.FILES
# <MultiValueDict: {u'profileImage': [<InMemoryUploadedFile: image.jpg (image/jpeg)>]}>
print request.DATA
# <QueryDict: {u"{'firstName':'hello'};content-type": [u'application/json']}>

图像没问题,但 QueryDict 没有正确表示 - 所有 JSON 文件都是键和内容类型 是一个值。

在 Django 中使用这些解析器:

parser_classes = (MultiPartParser, FormParser, JSONParser,)

我需要通过 JSON 结构发送文本数据。

【问题讨论】:

  • 您在视图中使用了哪些解析器?
  • parser_classes = (MultiPartParser, FormParser, JSONParser,) 我更新了问题

标签: python django curl django-rest-framework


【解决方案1】:

如果要使用multipart/form-data 内容类型进行发布,则不能同时指定application/json。解决此问题的简单方法是以 url 编码格式发送表单数据。试试这个命令:

curl -F "profileImage=@/home/user/image.jpg" -F "firstName=hello" http://127.0.0.1:8000/api/v1/signup/

【讨论】:

【解决方案2】:

我想出了一个这样的解决方案:

class MultiPartJSONParser(parsers.MultiPartParser):

    def parse(self, stream, media_type=None, parser_context=None):

        dataAndFiles = super(MultiPartJSONParser, self).parse(stream, media_type, parser_context)

        try:
            jsonData = json.loads(dataAndFiles.data.get('data'))
        except ValueError as exc:
            raise parsers.ParseError('JSON parse error - %s' % six.text_type(exc))

        # make data mutable, insert json data, and remove raw data
        dataAndFiles.data = data = dataAndFiles.data.copy()
        data.update(jsonData)
        del data['data']

        return dataAndFiles

假定 JSON 部分作为名为“数据”的表单字段发送。

如果你想变得非常流畅,你可以根据 Accept 标头的媒体类型值来解析数据字段。或者,您可以将数据作为文件发布并根据其内容类型进行解析。

请注意,要使用此解析器类,您需要设置以下默认设置:

REST_FRAMEWORK = {
    'FORM_METHOD_OVERRIDE': None,
    'FORM_CONTENT_OVERRIDE': None,
}

这是由于这个错误:https://github.com/tomchristie/django-rest-framework/issues/1346

【讨论】:

    【解决方案3】:

    指定内容类型的参数就是"type="

    curl -F "profileImage=@/home/user/image.jpg" -F "{'firstName':'hello'};type=application/json" http://127.0.0.1:8000/api/v1/signup/
    

    但是,我认为这不会允许 JSONParser 获取信息...,但您可以尝试 :)

    【讨论】:

    • 没有帮助。工作相同。我认为是同义词。用“类型”更新了问题。
    • 这不是 -F 标志的有效用法。它使用部件名称{'firstName':'hello'};type 和值application/json 发出请求
    【解决方案4】:

    这里:-

    curl -vvv -X POST -H "Content-Type:multipart/form-data" -H "Accept:application/json" -H -F "username=sample" -F "password=something" -F "image=@Mercury.gif" http://127.0.0.1:8000/api/objects
    

    无需输入接受应用程序/json。 Django 会自动将它们视为字典对象。

    打印 request.DATA 和 request.FILES 会给你

    <QueryDict: {u'username': [u'sample'] , u'password': [u'something']}>
    <MultiValueDict: {u'image': [<InMemoryUploadedFile: Mercury.gif (image/gif)>]}>
    

    【讨论】:

    • 谢谢,它解决了一半的问题。 Querydict 和 Image 到达很好,但我还需要通过 json 结构'{key: val, key: val} 发送文本数据。
    【解决方案5】:

    感谢 xjtian - 您在评论中粘贴的链接 + 一些研究解决了问题。 所以:

    1. 如果你想发送 json 数据 + 文件 - 发送两个请求。首先将在后端创建对象并将 id 提供给应用程序。其次将使用给定的 id 用文件更新对象。更多信息there

    2. 如果您不关心数据类型 - 通过“multipart/form-data”发送请求。

    感谢大家的回答,你们真的很有帮助,但我认为这个更适合 REST 架构。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-24
      • 2021-12-14
      • 1970-01-01
      • 2018-12-26
      • 2019-01-05
      • 1970-01-01
      • 1970-01-01
      • 2019-05-27
      相关资源
      最近更新 更多