python requests中以“multipart/form-data”方式上传文件的坑

本文探讨了Python的requests库在使用urllib3时,如何处理非ASCII文件名上传的问题。在1.25版本之前,urllib3遵循RFC2231标准将非ASCII文件名编码,可能导致某些未实现该标准的web服务无法正确解析。示例代码展示了上传英文和中文文件名的区别,并提供了相关代码片段和RFC链接来说明问题所在。
摘要由CSDN通过智能技术生成

requests依赖的urllib3库在1.25版本之前实现multipart/form-data方式上传时,实现了RFC2231,然而某些web服务可能并没有实现RFC2231,而导致服务端无法正常解析python客户端上传的文件。

import requests

rep = requests.post('http://127.0.0.1:5000/upload_file', files={'file': ('test.txt', open('test.txt',rb))})
rep1 = requests.post('http://127.0.0.1:5000/upload_file', files={'file': ('测试.txt', open('测试.txt',rb))})
print(rep.request.body.decode('utf8'))
print('=' * 20)
print(rep1.request.body.decode('utf8'))


输出:

--94db87fe35c9427fa76772e134f8c014
Content-Disposition: form-data; name="file"; filename="test.txt"

test
--94db87fe35c9427fa76772e134f8c014--
####################
--06a545bbec1c4b9592e208a4aa3520eb
Content-Disposition: form-data; name="file"; filename*=utf-8''%E6%B5%8B%E8%AF%95.txt

测试
--06a545bbec1c4b9592e208a4aa3520eb--

在上面的代码中,分别上传了一个非中文文件名文件和一个中文文件名的文件,根据RFC2231,中文名的filename转换成了filename*=utf-8''%E6%B5%8B%E8%AF%95.txt,这导致未实现RFC2231的web服务无法正常解析filename。


urllib3库中相关的代码urllib3/fields.py

def format_header_param(name, value):
    """
    Helper function to format and quote a single header parameter.

    Particularly useful for header parameters which might contain
    non-ASCII values, like file names. This follows RFC 2231, as
    suggested by RFC 2388 Section 4.4.

    :param name:
        The name of the parameter, a string expected to be ASCII only.
    :param value:
        The value of the parameter, provided as a unicode string.
    """
    if not any(ch in value for ch in '"\\\r\n'):
        result = '%s="%s"' % (name, value)
        try:
            result.encode('ascii')
        except (UnicodeEncodeError, UnicodeDecodeError):
            pass
        else:
            return result
    if not six.PY3 and isinstance(value, six.text_type):  # Python 2:
        value = value.encode('utf-8')
    value = email.utils.encode_rfc2231(value, 'utf-8')
    value = '%s*=%s' % (name, value)
    return value

相关链接

1、github上相关问题的issues
2、rfc2388
3、rfc2231

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值