如何向multipart/form-data发送文件?
我想在 http://www.broadinstitute.org/cmap/newQuery?servletAction=querySetup&queryType=quick
这个网站上上传和提交文件(需要登录)。这个表单看起来是这样的:
<form name="form1" enctype="multipart/form-data" method="post" action="newQuery">
<input type="hidden" name="servletAction" value="quickQuery">
<div class="formTable">
<div class="row">
<span class="label" style="width: 100px;">up tag file:</span>
<span class="field"><input type="file" name="ups" size="30" accept="grp"> <font size="-1"><a href="#" onClick="window.open('help_topics_frames.jsp?topic=tag list', 'helpTopicsWindow', 'scrollbars,resizable,height=600,width=700')">tag file help</a></font></span>
</div>
<div class="row">
<span class="label" style="width: 100px;">down tag file:</span>
<span class="field"><input type="file" name="dns" size="30" accept="grp"></span>
</div>
<div class="row">
<span class="label" style="width: 100px;"> </span>
<span class="navigation"><input type="button" onClick="submitForm()" name="submitButton" value="execute query"></span>
</div>
</div>
</form>
首先,我从这个回答 https://stackoverflow.com/a/22547541/651779 中获取了登录凭证的cookie。
import http.cookiejar
import urllib
from bs4 import BeautifulSoup
import requests
submit_signature_url = 'http://www.broadinstitute.org/cmap/newQuery?servletAction=querySetup&queryType=quick'
login_url = 'http://www.broadinstitute.org/cmap/j_security_check'
login_values = urllib.parse.urlencode({'j_username': 'example',
'j_password': 'example',
'submit': 'sign in'})
payload_submit_signature = bytes(login_values, 'ascii')
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(
urllib.request.HTTPRedirectHandler(),
urllib.request.HTTPHandler(debuglevel=0),
urllib.request.HTTPSHandler(debuglevel=0),
urllib.request.HTTPCookieProcessor(cj))
resp_1 = opener.open(submit_signature_url) #First call to capture the JSESSIONID
resp = opener.open(login_url, payload_submit_signature)
这个步骤是正确的。现在我想把文件提交到这个表单。我尝试使用这个回答 https://stackoverflow.com/a/12385661/651779。
# changed after Brett Lempereur's answer
values = {'ups':open(r'path\to\up.grp','rb'),
'dns':open(r'path\to\down.grp','rb')}
submit_signature_url = 'http://www.broadinstitute.org/cmap/newQuery?servletAction=querySetup&queryType=quick'
req = requests.post(submit_signature_url, files=values, cookies=cj)
soup = BeautifulSoup(req.text)
print(soup.prettify())
这个操作打印出了:
Requested URL: http://www.broadinstitute.org/cmap/newQuery
java.lang.NullPointerException
如果你已经登录,并在浏览器中访问 http://www.broadinstitute.org/cmap/newQuery,你会看到同样的内容。如果我在 requests.post 中使用 data
而不是 files
:req = requests.post(submit_signature_url, data=values, cookies=cj)
,它会打印出包含表单的页面的html,所以并没有成功提交表单。
我该如何提交 multipart/form-data 格式的数据呢?
关于上传文件的示例,可以把以下内容复制到一个文件中,并命名为 up.grp:
205258_at
221369_at
205751_at
212954_at
219914_at
206703_at
207352_s_at
203548_s_at
203549_s_at
210382_at
212110_at
213805_at
213935_at
218739_at
219737_s_at
219738_s_at
204131_s_at
204132_s_at
210655_s_at
217399_s_at
206791_s_at
206792_x_at
211818_s_at
221523_s_at
221524_s_at
关于下载文件的示例,可以把以下内容复制到一个文件中,并命名为 down.grp:
204725_s_at
211063_s_at
219921_s_at
200618_at
219701_at
220342_x_at
220926_s_at
201323_at
204692_at
221956_at
222017_x_at
90610_at
217755_at
207843_x_at
209366_x_at
215726_s_at
201827_at
201185_at
212411_at
201692_at
214484_s_at
202910_s_at
202381_at
200663_at
201459_at
219770_at
220853_at
201349_at
207015_s_at
207016_s_at
212338_at
220330_s_at
1 个回答
我来猜一下,当前版本的requests模块希望它的参数有以下几种格式:
files = {"name": file-handle, ...}
files = {"name": (file-name, file-handle, content-type,), ...}
你有没有试过把你创建文件字典的方式换成类似下面的写法:
values = {'ups': open(r'path\to\up.grp', 'rb'), 'dns': open(r'path\to\down.grp', 'rb')}
你的代码在技术上是对的,但在语义上不太正确,因为一些文件数据会被发送到网站上,但实际上发送的内容是字符串字面量r'path\to\up.grp'的内容。
从表单来看,你还应该把字典{"servletAction": "quickQuery"}
作为数据参数传给requests.post
调用。此外,你要发送请求的URL应该是http://www.broadinstitute.org/cmap/newQuery
,而不是你在原始代码中使用的那个查询字符串。