如何添加perfile自定义头到多部分上传请求?

2024-09-29 02:28:53 发布

您现在位置:Python中文网/ 问答频道 /正文

python请求似乎支持将自定义集合作为要上载的文件的列表/映射。在

这反过来应该允许我添加自定义头字段,每个文件都在一个多部分上载中上载。在

我怎么能做到呢?在


Tags: 文件列表头字段
1条回答
网友
1楼 · 发布于 2024-09-29 02:28:53

python-requests appears to support custom collections as a list/mapping of files to upload.

This in turn should allow me to add custom header fields with each file being uploading within one multipart upload.

没有。列表/映射中的每个文件必须是文件对象(或内容字符串)、文件名和文件对象(或内容)的2元组,或文件名、文件对象(或内容)和文件类型的3元组。其他的都是非法的。在

除非#1640在上游被接受,在这种情况下,您只需使用文件名、文件对象(或内容)、文件类型和头字典的4元组。在


此时正确的做法可能是使用不同的库。例如,如果您直接使用urllib3,而不是通过request包装,那么您想做的事情就相当容易了。您只需处理使用urllib3而不是requests的所有额外冗长。在

同时,您可以针对requests提交一个特性请求,将来可能会添加一个更简单的方法。在


但有点令人沮丧的是,你所需要的功能都在幕后,你就是无法实现它。在

看起来干净利落的做事会是一场噩梦。我们可以很容易地破解代码。在

看看^{}。它希望files中的每个文件都是文件名、内容或文件对象的元组,并且可以选择内容类型。它基本上只是读入任何文件对象以将其转换为内容,并将所有内容直接传递到urllib3.filepost.encode_multipart_formdata。所以,除非我们想替换这个代码,否则我们需要用这些值中的一个来偷运头。让我们传递(filename, contents, (content_type, headers_dict))。所以,requests本身没有变化。在

那它叫的^{}呢?如您所见,如果您将文件的元组传递给它,它将调用一个名为^{}的函数,该函数最终对每个文件调用^{}。但是如果你看一下from_tuples替代构造函数,它说它是用来处理构造RequestField对象的“旧式”方法的,而普通的构造函数则是“新样式”的,它实际上允许你传入头。在

所以,我们需要做的就是monkeypatch iter_field_objects,用一个使用新样式的方法替换它的最后一行,我们就应该完成了。让我们试试:

import requests
import requests.packages.urllib3
from requests.packages.urllib3.fields import RequestField, guess_content_type
import six

old_iter_field_objects = requests.packages.urllib3.filepost.iter_field_objects
def iter_field_objects(fields):
    if isinstance(fields, dict):
        i = six.iteritems(fields)
    else:
        i = iter(fields)

    for field in i:
      if isinstance(field, RequestField):
        yield field
      else:
        name, value = field
        filename = value[0]
        data = value[1]
        content_type = value[2] if len(value)>2 else guess_content_type(filename)
        headers = None
        if isinstance(content_type, (tuple, list)):
            content_type, headers = content_type
        rf = RequestField(name, data, filename, headers)
        rf.make_multipart(content_type=content_type)
        yield rf
requests.packages.urllib3.filepost.iter_field_objects = iter_field_objects

现在:

^{pr2}$

泰达!在

请注意,您需要相对最新的requests/urllib3才能工作。我认为requests2.0.0就足够了。在

相关问题 更多 >