我有以下代码:
r = requests.put( config.get('webdav', 'url') + file_name, auth=( config.get('webdav', 'username'), config.get('webdav', 'password') ), files={ "files": open(os.path.expanduser(charges_file_path), 'rb') } )
这相当简单。它只是PUT向 webdav 服务器发出请求,并将文件中的数据(纯文本)推送到服务器。
PUT
它能正常工作,除了一个奇怪的问题(或者如果我只是忽略了一些小问题,可能就不那么奇怪了)。当我GET对文件执行操作时,或者直接在服务器上查看文件时,文件本身包含标头信息:
GET
–55e72d74a10b423590cd4faa68212192 内容处置:表单数据;名称=“文件”;文件名=“test_file6.txt” (文件数据) –55e72d74a10b423590cd4faa68212192–
–55e72d74a10b423590cd4faa68212192 内容处置:表单数据;名称=“文件”;文件名=“test_file6.txt”
(文件数据)
–55e72d74a10b423590cd4faa68212192–
我还没能找到原因或解决方法。当我从命令行 cURL 文件时,它工作正常。
有什么想法吗?
这个问题通常发生在你上传文件时,requests 库默认会使用 multipart/form-data 来发送文件,而 PUT 请求通常不需要这些额外的表单标头。multipart/form-data 格式包含 Content-Disposition 标头,它指定了文件上传的元数据(例如文件名)。而你在服务器端获取的文件中显示了这些表单标头,可能是由于请求的内容类型或文件上传方式不符合你的预期。
requests
multipart/form-data
Content-Disposition
你希望文件直接作为纯文本上传,而不是通过表单数据上传,因此你不应该将文件包裹在 files 字段中,这会导致 requests 使用 multipart/form-data。相反,应该以字节流的形式上传文件。你可以通过以下方法修改代码:
files
import requests import os from configparser import ConfigParser # 配置文件 config = ConfigParser() config.read('config.ini') # 读取文件路径 charges_file_path = '/path/to/your/file.txt' file_name = 'test_file6.txt' # 打开文件并将其内容直接发送 with open(os.path.expanduser(charges_file_path), 'rb') as file_data: r = requests.put( config.get('webdav', 'url') + file_name, auth=( config.get('webdav', 'username'), config.get('webdav', 'password') ), data=file_data # 使用data而不是files ) print(r.status_code)
在这个方法中,文件内容被直接发送到 PUT 请求的正文中,而不使用 files 字段,这样就避免了 Content-Type: multipart/form-data 和额外的标头。data=file_data 会将文件作为原始字节流上传,WebDAV 服务器应该接收并存储这个文件,而不再包含表单标头。
Content-Type: multipart/form-data
data=file_data
如果你仍然希望使用 files 字段上传文件(通常是处理文件上传时使用),你可以显式地设置 Content-Type,以避免 requests 自动生成 multipart/form-data 类型。
Content-Type
import requests import os from configparser import ConfigParser # 配置文件 config = ConfigParser() config.read('config.ini') # 读取文件路径 charges_file_path = '/path/to/your/file.txt' file_name = 'test_file6.txt' # 打开文件并设置适当的 Content-Type with open(os.path.expanduser(charges_file_path), 'rb') as file_data: headers = { 'Content-Type': 'application/octet-stream', # 你可以根据需要选择合适的内容类型 } r = requests.put( config.get('webdav', 'url') + file_name, auth=( config.get('webdav', 'username'), config.get('webdav', 'password') ), data=file_data, headers=headers ) print(r.status_code)
通过手动设置 Content-Type 为 application/octet-stream 或其他合适的 MIME 类型,你可以避免 requests 自动使用 multipart/form-data。
application/octet-stream
通过这些修改,你应该能够避免在文件内容中看到额外的表单标头。