2024-09-29 02:28:53 发布
网友
python请求似乎支持将自定义集合作为要上载的文件的列表/映射。在
这反过来应该允许我添加自定义头字段,每个文件都在一个多部分上载中上载。在
我怎么能做到呢?在
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.
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的所有额外冗长。在
urllib3
request
requests
同时,您可以针对requests提交一个特性请求,将来可能会添加一个更简单的方法。在
但有点令人沮丧的是,你所需要的功能都在幕后,你就是无法实现它。在
看起来干净利落的做事会是一场噩梦。我们可以很容易地破解代码。在
看看^{}。它希望files中的每个文件都是文件名、内容或文件对象的元组,并且可以选择内容类型。它基本上只是读入任何文件对象以将其转换为内容,并将所有内容直接传递到urllib3.filepost.encode_multipart_formdata。所以,除非我们想替换这个代码,否则我们需要用这些值中的一个来偷运头。让我们传递(filename, contents, (content_type, headers_dict))。所以,requests本身没有变化。在
files
urllib3.filepost.encode_multipart_formdata
(filename, contents, (content_type, headers_dict))
那它叫的^{}呢?如您所见,如果您将文件的元组传递给它,它将调用一个名为^{}的函数,该函数最终对每个文件调用^{}。但是如果你看一下from_tuples替代构造函数,它说它是用来处理构造RequestField对象的“旧式”方法的,而普通的构造函数则是“新样式”的,它实际上允许你传入头。在
from_tuples
所以,我们需要做的就是monkeypatch iter_field_objects,用一个使用新样式的方法替换它的最后一行,我们就应该完成了。让我们试试:
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
现在:
泰达!在
请注意,您需要相对最新的requests/urllib3才能工作。我认为requests2.0.0就足够了。在
没有。列表/映射中的每个文件必须是文件对象(或内容字符串)、文件名和文件对象(或内容)的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
,用一个使用新样式的方法替换它的最后一行,我们就应该完成了。让我们试试:现在:
^{pr2}$泰达!在
请注意,您需要相对最新的
requests
/urllib3
才能工作。我认为requests
2.0.0就足够了。在相关问题 更多 >
编程相关推荐