2012-09-25 133 views
5

我想知道你如何使用Python请求翻译类似的东西?在urllib2中,您可以手动操作通过线路发送到API服务的数据,但请求声明多部分文件上传很容易。但是,当试图使用请求库发送相同的请求时,我相信它没有正确指定内容类型中的每个部分的某些关键参数。有人可以谈谈这件事。先谢谢你!Python请求Multipart HTTP POST

def upload_creative(self, account_id, file_path): 
    """""" 
    boundary = '-----------------------------' + str(int(random.random()*1e10)) 
    parts = [] 

    # Set account ID part. 
    parts.append('--' + boundary) 
    parts.append('Content-Disposition: form-data; name="account_id"') 
    parts.append('') 
    parts.append(str(account_id)) 

    # Set creative contents part. 
    parts.append('--' + boundary) 
    parts.append('Content-Disposition: form-data; name="userfile"; filename="%s"' % file_path) 
    parts.append('Content-Type: %s' % mimetypes.guess_type(file_path)[0] or 'application/octet-stream') 
    parts.append('') 
    # TODO: catch errors with opening file. 
    parts.append(open(file_path, 'r').read()) 

    parts.append('--' + boundary + '--') 
    parts.append('') 

    body = '\r\n'.join(parts) 

    headers = {'content-type': 'multipart/form-data; boundary=' + boundary} 
    url = self._resolve_url('/a/creative/uploadcreative') 
    req = urllib2.Request(url, headers=headers, data=body) 
    res = urllib2.urlopen(req) 

    return json.loads(res.read()) 

当我从UI检查萤火虫时,我在POST源代码中得到以下内容。是

-----------------------------662549079759661058833120391 
Content-Disposition: form-data; name="userfile"; filename="IMG_1377.jpg" Content-Type: image/jpeg 

ÿØÿáÃExif��MM�*���� �������ª���� ���°���������������������º�������Â(�������1�������Ê2�������Ú<�������î�������i�������þ%������p��Apple�iPhone 4���H������H�����QuickTime 7.7.1�2012:08:17 11:47:11�Mac OS X 10.7.4�������������� "�������'�����P�������0220������(������<������ �����P������X������� ����� �� ������`������h �����0100 ������� ������ ������¢�������¤��������¤��������¤��������¤ ����������������������2011:10:01 17:19:23�2011:10:01 17:19:23���4��Á��¹��¡���M���Ç»¸������N����������Ê�����W����������â�������ú�����M�����������������!�����S���d����������T�����ÿ���d���������������������Ú����%Á��r��������������t������|(�������������������7������������H������H�����ÿØÿà�JFIF��H�H��ÿþ�AppleMark ÿÛ�� % #!,!#'(***.1-)1%)*((((((((((((((((((((((((((((((((((((((((((((((((((((ÿÄ¢���������� ������� ���}�!1AQa"q2¡#B±ÁRÑð$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚáâãäåæçèéêñòóôõö÷øùú��w�!1AQaq"2B¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz¢£¤¥¦§¨©ª²³´µ¶·¸¹ð.¥ÛWíÇLòV³FcaoæÂÒ8§É¸(è3E¢"Ú×S^+yj�!òû0Oüµn- yè){[oÝ/¸?ÃÔMY¡ÃgÔò4êò4n͸í¶={ÔM¤¸m¯K&ñæ«,©ù»zTÝ=öØô×6¶Ö:MÑi�,Û$Oö[ª÷ª©ÆiîỤJAxj>ÞAõúu¥}lIf÷û^Â)#´y^)Ô"/·v>n~4ººµ­¬æ}FURì·Î 3¿Ãèh»ÐµÈÿ�·|Gu:ß²<ëlWäG·^+¡Ó¼gâ.-Þè|ϸ*ª® }é?Ú=(i:2½Ïg!ʵÑi¤¼eþ!÷³ÍC'æCqv®ÖÊÕiçCë·øsQy#K_B´þ0s'¦|¿Þ²lò¼?½ÿ�]rZ¶¨ø·6ñÆØ·mvV;þÿ�þ=ôª¿»r\zPñtHö÷>Ù¤R#+ Á òBôR;ú²¾)!àËn<.ÁÔlÏcRäÂ&§­eX´fTóLžQßt§Zµ{â t·pK]ÈL1²îýúEüxþ÷j\î×-jÏÂ>!û:^,E­,>^ýêßwû+Ópæ»?i÷û5kéá¹^ 6Ddq°öÁ¯Rù¨¦yãjòÿÙ 
-----------------------------662549079759661058833120391 
Content-Disposition: form-data; name="account_id" 

69574 
-----------------------------662549079759661058833120391-- 

在萤火虫的标题如下:

Request Headersview source 
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Encoding gzip, deflate 
Accept-Language en-us,en;q=0.5 
Cache-Control no-cache 
Connection keep-alive 
Content-Length 1713991 
Content-Type multipart/form-data; boundary=---------------------------662549079759661058833120391 
Cookie instance_defaults=%7C%20%7Cen_US; access_token=75c48e 
Host ui.host.com 
Pragma no-cache 
Referer http://ui.host.com/ 
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:14.0) Gecko/20100101 Firefox/14.0.1 

我想我的问题是有没有通过请求库的方式来调整数据,这样的:

Content-Disposition: form-data; name="userfile"; filename="IMG_1377.jpg" Content-Type: image/jpeg 

Content-Disposition: form-data; name="account_id" 

69574 

sta帐单都存在。我觉得我会做这样的事情有文件是

files = {'file': open('image.jpg', 'rb'), 'account_id': 12345} 

一本字典,但不知何故编辑每个部分的内容处理元数据分开

+0

是什么?你用'requests'尝试? –

+0

我正在尝试编辑多部分文件上载POST请求的每个部分的Content-Disposition元数据。例如在我的编辑中,我需要有 name =“userfile”;文件名=“IMG_1377.jpg”Content-Type:image/jpeg 第一部分是图像文件,然后是第二部分,我需要有 Content-Disposition:form-data; name =“account_id” 我希望这会给问题带来一些清晰。请让我知道如果这样的事情是可能的python请求库。非常感谢 – user1698138

回答

8

requests,我相信,你不”吨有如此手册,简单地说:

import requests 

# ... 
url = self._resolve_url('/a/creative/uploadcreative') 
files = {'file': ('userfile', open(filepath, 'rb'))} 
data = {'account_id': account_id} 
headers = {'content-type': 'multipart/form-data'} 
res = requests.post(url, files=files, data=data, headers=headers) 
return res.json 

我想你的关心在于你:

parts.append('Content-Type: %s' % mimetypes.guess_type(file_path)[0] or 'application/octet-stream') 

我还没有证明自己超越了怀疑的阴影。但是,我认为这是建立在请求here

编辑:looks like你可以在文件的正常领域快译通,你建议:

files = {'file': open('image.jpg', 'rb'), 'account_id': 12345} 

并根据需要可以命名文件名:

files = {'file': ('userfile', open('image.jpg', 'rb')), 'account_id': 12345} 

但是,你会在account_id字段上获得body.write(b'Content-Type: text/plain\r\n\r\n'),这可能不是您想要的,并且无法为每个字段自定义内容处置(仍然不确定为什么需要);对于文件和字段,您将获得:Content-Disposition: form-data - 这是您为两者展示的内容。

我不确定你可以用requests来完成你想要的,也许你应该尝试一个功能请求。

+1

确切地说,有时您仍然需要指定标头,因为有一些限制。请求使用'urlib3',所以它非常好。 – CppLearner

+0

那么,你可以用'requests'手动指定文件的内容类型吗?它似乎使用与问题相同的启发式,但似乎没有提供手动指定文件CT的方法。 –

+0

但是我明白,我不认为这是我的问题的答案。我已经编辑了我的问题并进行了更多的澄清,希望有人能够得到我正在寻找的答案。非常感谢大家 – user1698138

-3

我发现在python-requests库(v.0.13.3)中,如果在请求调用本身的“files”字段之前包含“data”字段,将会擦除数据。

例如,

requests.post(url, headers=headers, data=data, files=files) 

将产生空形式的数据。但是,以下将发送数据字典的形式数据

requests.post(url, headers=headers, files=files, data=data) 

谢谢大家对他们的答案

+0

Python中命名参数的顺序无关紧要 - 这两个调用完全相同。您观察到的行为是因为您可能在'data'参数中发送了不同类型的值 - 请参阅[this](http://stackoverflow.com/a/12385661/95735)答案。 –

0
import requests 

import urllib 

def upload_creative(self, account_id, file_path): 

    files = [('userfile', (file_path, open(file_path, 'rb'), "image/jpeg"))] 

    url = self._resolve_url('/a/creative/uploadcreative') 

    url = url + "?" + urlib.urlencode(account_id=account_id) 

    reuests.post(url, files=files)