提交表单并上传包含请求的文件

时间:2013-11-16 14:32:09

标签: python python-requests

我在努力提交python requests的特定表单。网站上的其他表单我想使用它工作正常,我能够提交登录表单等。这只是文件上传我遇到了问题。显然提交表单工作正常,因为我从网站收到一条消息说“请返回并选择至少一个要上传的图像文件”。但该文件未发布到该网站。

如果我使用Firefox插件Tamperdata查看请求,我提交空表单后会看起来像这样:

-----------------------------201075691119887339851216603987\r
Content-Disposition: form-data; name="userfile[]"; filename=""\r
Content-Type: application/octet-stream\r
\r
\r
-----------------------------201075691119887339851216603987\r
Content-Disposition: form-data; name="userfile[]"; filename=""\r
Content-Type: application/octet-stream\r
\r
\r
-----------------------------201075691119887339851216603987\r
Content-Disposition: form-data; name="userfile[]"; filename=""\r
Content-Type: application/octet-stream\r
\r
\r
-----------------------------201075691119887339851216603987\r
Content-Disposition: form-data; name="userfile[]"; filename=""\r
Content-Type: application/octet-stream\r
\r
\r
-----------------------------201075691119887339851216603987\r
Content-Disposition: form-data; name="userfile[]"; filename=""\r
Content-Type: application/octet-stream\r
\r
\r
-----------------------------201075691119887339851216603987\r
Content-Disposition: form-data; name="upload_to"\r
\r
0\r
-----------------------------201075691119887339851216603987\r
Content-Disposition: form-data; name="upload_type"\r
\r
standard\r
-----------------------------201075691119887339851216603987--\r

(我用换行符替换了所有\ n,使其更具可读性)

我的python上传代码如下所示:

index = s.get("https://example.com/")
file = {'userfile[]': open('tmp/cover/cover.jpg', 'rb')}

res = s.post(url='https://example.com/upload.php',
                data=file,
                headers={'Content-Type': 'application/octet-stream'})

HTML表单如下所示:

<form action="upload.php" method="post" id="upload_form" enctype="multipart/form-data">
    <p>
        <input name="userfile[]" type="file" size="30"> <br>
        <input name="userfile[]" type="file" size="30"> <br>
        <input name="userfile[]" type="file" size="30"> <br>
        <input name="userfile[]" type="file" size="30"> <br>
        <input name="userfile[]" type="file" size="30"> <br>

        <span id="more_file_inputs"></span>
        <br>
        <span id="upoptions_hidden">
            Uploading Options: <a href="javascript:void(0);" onclick="toggle('upoptions_hidden'); toggle('upoptions_shown');">Show</a>
        </span>

        <span id="upoptions_shown" style="display: none;">
            Uploading Options: <a href="javascript:void(0);" onclick="toggle('upoptions_hidden'); toggle('upoptions_shown');">Hide</a>
            <br><br>

                                Upload to: 
                <select name="upload_to">

                    <option value="0">Root Album</option>

                </select>
                <br><br>


           Output Layout: <input type="radio" name="upload_type" value="standard" checked="checked"> <span onclick="toggle_lightbox('index.php?layoutprev=std', 'upload_layout_preview_lightbox');" title="Click to preview" class="help">Standard</span> <input type="radio" name="upload_type" value="normal-boxed"> <span onclick="toggle_lightbox('index.php?layoutprev=bx', 'upload_layout_preview_lightbox');" title="Click to preview" class="help">Boxed</span>
        </span>
        <br><br>

        <input class="button1" type="button" value="Add File" onclick="new_file_input();"> 
        <input class="button1" style="font-weight:bold;" type="button" value="Start Upload" onclick="toggle_lightbox('index.php?act=upload_in_progress', 'progress_bar_lightbox'); $('form[id=upload_form]').submit();">
    </p>
</form>

有关这里有什么问题的想法或更好的调试方法吗?谢谢!

编辑:我刚才意识到我并没有真正提交upload_typeupload_to字段,但即使我将它们设置为:

file = {'userfile[]': open('tmp/cover/cover.jpg', 'rb'), 'upload_to': '0', 'upload_type': 'standard'}

它还没有用。

2 个答案:

答案 0 :(得分:4)

使用files关键字进行上传,而不是data。不要设置内容类型标题;表单作为多部分表单数据发布,请求应为您使用正确的内容类型:

res = s.post(
    url='https://example.com/upload.php',
    data={'upload_type': 'standard', 'upload_to': '0'},
    files=file)

并将其余表单字段放在data

中的映射中

如果您要使用相同名称上传多个文件,请使用序列文件:

files = {
    'userfile[]': [
        open('tmp/cover/cover1.jpg', 'rb'),
        open('tmp/cover/cover2.jpg', 'rb'),
    ]
}

res = s.post(
    url='https://example.com/upload.php',
    data={'upload_type': 'standard', 'upload_to': '0'},
    files=files)

答案 1 :(得分:4)

我发现您的代码有两个问题:

  • 您正在手动设置内容类型。的不要即可。图书馆将负责这一点。这是特别的。因为在多部分表单数据发布期间,标题类似于:Content-Type: multipart/form-data; boundary=<blah>
  • According the docs,您应该使用 files 命名参数来上传文件,而不是data

使用:

res = s.post(url='https://example.com/upload.php',
            data=<dict containing form params>,
            files=file)