MultiPartParserError :- 边界无效 [英] MultiPartParserError :- Invalid boundary

查看:36
本文介绍了MultiPartParserError :- 边界无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Python requests 模块向我的 django rest 应用程序发送一些数据和文件,但出现以下错误.

 raise MultiPartParserError('无效的多部分边界:%s' %边界)MultiPartParserError:多部分中的边界无效:无

代码:-

导入请求有效载荷 = {'管理员':[{'first_name':'约翰','last_name':'白','job_title':'CEO','email':'test1@gmail.com'},{'名字':'丽莎','last_name':'markel','job_title':'CEO','email':'test2@gmail.com'}],'company-detail':{'description':'我们是一家著名的工程公司','尺寸':'1-10','行业':'工程','url':'http://try.com','标识':'','addr1':'1280 灯芯','addr2':'1600','城市':'克维尔','state':'md','zip_cd':'12000','phone_number_1':'408-393-254','phone_number_2':'408-393-221','company_name':'GOOGLE'}}files = {'upload_file':open('./test.py','rb')}导入json标头 = {'内容类型':'应用程序/json'}headers = {'content-type':'multipart/form-data'}#r = requests.post('http://127.0.0.1:8080/api/create-company-profile/',data=json.dumps(payload),headers=headers,files=files)r = requests.post('http://127.0.0.1:8080/api/create-company-profile/',data=payload,headers=headers,files=files)打印 r.status_code打印 r.text

Django 代码:-

class CompanyCreateApiView(CreateAPIView):parser_classes = (MultiPartParser, FormParser,)def post(self, request, *args, **kwargs):打印 'request ==', request.data

解决方案

好吧,我忘了你的标题.根据规范:

<块引用>

Content-Type = "Content-Type" ":" media-type

MIME 提供了许多多部分"类型——封装单个消息正文中的一个或多个实体.所有多部分类型共享一个通用语法,...并且必须包含一个边界参数作为媒体类型的一部分价值.

以下是包含 multipart/form-data 的请求的样子:

POST/myapp/company/HTTP/1.1主机:本地主机:8000内容长度:265接受编码:gzip、deflate接受: */*用户代理:python-requests/2.9.0连接:保持连接内容类型:多部分/表单数据;边界=63c5979328c44e2c869349443a94200e--63c5979328c44e2c869349443a94200e内容配置:表单数据;名称=你好"世界--63c5979328c44e2c869349443a94200e内容配置:表单数据;名称=我的数据";文件名=数据.txt"1号线2号线3号线4号线--63c5979328c44e2c869349443a94200e--

看看数据部分是如何被边界分隔的:

--63c5979328c44e2c869349443a94200e--

这个想法是使用一些不太可能出现在数据中的边界.请注意,边界包含在请求的 Content-Type 标头中.

该请求是由以下代码生成的:

导入请求myfile = {'mydata': open('data.txt','rb')}r = requests.post(网址,#headers = 我的标题数据 = {'你好':'世界'},文件 = 我的文件)

您似乎很注意 django-rest-framework 中的以下注释 文档:

<块引用>

注意:在开发客户端应用程序时,请始终记得确保您在 HTTP 中发送数据时设置 Content-Type 标头请求.

如果不设置内容类型,大多数客户端会默认使用'application/x-www-form-urlencoded',这可能不是您想要的.

但是当您使用 requests 时,如果您自己指定 Content-Type 标头,则 requests 假定您知道您的重新做,它不会用它提供的 Content-Type 标头覆盖您的 Content-Type 标头.

您没有按照要求在 Content-Type 标头中提供边界.你怎么能?您没有组装请求的正文并创建边界来分隔各种数据,因此您不可能知道边界是什么.

django-rest-framework 注释说您应该在请求中包含 Content-Type 标头时,这真正意味着:

<块引用>

您或您用于创建请求的任何程序都需要包含Content-Type 标头.

所以@AChampion 在评论中是完全正确的:让 requests 提供 Content-Type 标头,毕竟 requests 文档做了广告:

<块引用>

Requests 完成了 Python HTTP/1.1 的所有工作

requests 的工作方式如下:如果您提供 files 关键字参数,则请求使用 multipart 的 Content-Type 标头/form-data 并且还指定了标题中的边界;然后 requests 使用边界组合请求的主体.如果您提供 data 关键字参数,则请求使用 application/x-www-form-urlencodedContent-Type,它只是组装所有字典中的键和值转换成这种格式:

x=10&y=20

不需要边界.

并且,如果您同时提供 files 关键字 arg 和 data 关键字 arg,则请求使用 Content-Type>multipart/form-data.

Im trying to send some data and file using Python requests module to my django rest application but get the below error.

    raise MultiPartParserError('Invalid boundary in multipart: %s' % boundary)
MultiPartParserError: Invalid boundary in multipart: None

Code:-

import requests
payload={'admins':[
                    {'first_name':'john'
                    ,'last_name':'white'
                    ,'job_title':'CEO'
                    ,'email':'test1@gmail.com'
                    },
                    {'first_name':'lisa'
                    ,'last_name':'markel'
                    ,'job_title':'CEO'
                    ,'email':'test2@gmail.com'
                    }
                    ],
        'company-detail':{'description':'We are a renowned engineering company'
                    ,'size':'1-10'
                    ,'industry':'Engineering'
                    ,'url':'http://try.com'
                    ,'logo':''
                    ,'addr1':'1280 wick ter'
                    ,'addr2':'1600'
                    ,'city':'rkville'
                    ,'state':'md'
                    ,'zip_cd':'12000'
                    ,'phone_number_1':'408-393-254'
                    ,'phone_number_2':'408-393-221'
                    ,'company_name':'GOOGLE'}
        }
files = {'upload_file':open('./test.py','rb')}
import json
headers = {'content-type' : 'application/json'}      
headers = {'content-type' : 'multipart/form-data'}      

#r = requests.post('http://127.0.0.1:8080/api/create-company-profile/',data=json.dumps(payload),headers=headers,files=files)
r = requests.post('http://127.0.0.1:8080/api/create-company-profile/',data=payload,headers=headers,files=files)
print r.status_code
print r.text

Django code:-

class CompanyCreateApiView(CreateAPIView):
    parser_classes = (MultiPartParser, FormParser,)
    def post(self, request, *args, **kwargs):
        print 'request ==', request.data

解决方案

Okay, I forgot about your headers. According to the spec:

Content-Type   = "Content-Type" ":" media-type

MIME provides for a number of "multipart" types -- encapsulations of one or more entities within a single message-body. All multipart types share a common syntax, ... and MUST include a boundary parameter as part of the media type value.

Here is what a request containing multipart/form-data looks like:

POST /myapp/company/ HTTP/1.1
Host: localhost:8000
Content-Length: 265
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.9.0
Connection: keep-alive
Content-Type: multipart/form-data; boundary=63c5979328c44e2c869349443a94200e   

--63c5979328c44e2c869349443a94200e
Content-Disposition: form-data; name="hello"

world
--63c5979328c44e2c869349443a94200e
Content-Disposition: form-data; name="mydata"; filename="data.txt"

line 1
line 2
line 3
line 4

--63c5979328c44e2c869349443a94200e--

See how the sections of data are separated by the boundary:

--63c5979328c44e2c869349443a94200e--

The idea is to use something for a boundary that is unlikely to appear in the data. Note that the boundary was included in the Content-Type header of the request.

That request was produced by this code:

import requests

myfile = {'mydata': open('data.txt','rb')}

r = requests.post(url, 
        #headers = myheaders
        data = {'hello': 'world'}, 
        files = myfile
) 

It looks like you were paying careful attention to the following note in the django-rest-framework docs:

Note: When developing client applications always remember to make sure you're setting the Content-Type header when sending data in an HTTP request.

If you don't set the content type, most clients will default to using 'application/x-www-form-urlencoded', which may not be what you wanted.

But when you are using requests, if you specify the Content-Type header yourself, then requests assumes that you know what you're doing, and it doesn't overwrite your Content-Type header with the Content-Type header it would have provided.

You didn't provide the boundary in your Content-Type header--as required. How could you? You didn't assemble the body of the request and create a boundary to separate the various pieces of data, so you couldn't possibly know what the boundary is.

When the django-rest-framework note says that you should include a Content-Type header in your request, what that really means is:

You or any programs you use to create the request need to include a Content-Type header.

So @AChampion was exactly right in the comments: let requests provide the Content-Type header, after all the requests docs advertise:

Requests takes all of the work out of Python HTTP/1.1

requests works like this: if you provide a files keyword arg, then requests uses a Content-Type header of multipart/form-data and also specifies a boundary in the header; then requests assembles the body of the request using the boundary. If you provide a data keyword argument then requests uses a Content-Type of application/x-www-form-urlencoded, which just assembles all the keys and values in the dictionary into this format:

x=10&y=20

No boundary required.

And, if you provide both a files keyword arg and a data keyword arg, then requests uses a Content-Type of multipart/form-data.

这篇关于MultiPartParserError :- 边界无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆