【问题标题】:How do I use requests.put() to upload a file using Python?如何使用 requests.put() 通过 Python 上传文件?
【发布时间】:2018-05-26 16:05:36
【问题描述】:

我正在尝试使用 Python 中的请求库将文件上传到本地主机上的 Fedora 公共存储库。我相当确定我的主要问题是不理解 open() / read() 以及使用 http 请求发送数据需要做什么。

def postBinary(fileName,dirPath,url):
    path = dirPath+'/'+fileName
    print('to ' + url + '\n' + path)
    openBin = {'file':(fileName,open(path,'rb').read())}
    headers = {'Slug': fileName} #not important
    r = requests.put(url, files=openBin,headers=headers, auth=HTTPBasicAuth('username', 'pass'))
    print(r.text)
    print("and the url used:")
    print(r.url)

这将成功地在存储库中上传一个文件,但之后它会稍大并损坏。例如,一个 6.6kb 的图像变成了 6.75kb 并且无法再打开。

那么我应该如何在 python 中使用 put 正确打开和上传文件?

###额外细节:###

  • 当我用data=openBin 替换files=openBin 时,我最终得到了我的字典,并且我假设数据是一个字符串。我不知道这些信息是否有用。
    “文件=FILE_NAME.extension&file=TYPE89a%24%02Q%03%E7%FF%00E%5B%19%FC%.... 并且文件的大小增加到数兆字节

  • 我使用的是专门 put 因为 Fedora RESTful HTTP API 端点说要使用put

以下命令确实有效:

curl -u username:password -H "Content-Type: text/plain" -X PUT -T /path/to/someFile.jpeg http://localhost:8080/fcrepo/rest/someFile.jpeg

【问题讨论】:

  • 看看here(使用POST方法)或here(使用PUT方法)。
  • 帖子信息对我没有帮助,异常说套接字协议错误。您发送的 PUT 方法链接我已经尝试过也没有运气:( 创建了一个损坏的文件

标签: python encoding python-requests fedora-commons


【解决方案1】:

更新

requests.put()files 参数一起使用会发送一个multipart/form-data 编码请求,服务器似乎无法在不破坏数据的情况下处理该请求,即使声明了正确的内容类型也是如此。

curl 命令仅使用请求正文中包含的原始数据执行 PUT。您可以通过在data 参数中传递文件数据来创建类似的请求。在 header 中指定内容类型:

headers = {'Content-type': 'image/jpeg', 'Slug': fileName}
r = requests.put(url, data=open(path, 'rb'), headers=headers, auth=('username', 'pass'))

您可以根据需要更改 Content-type 标头以适应有效负载。


尝试为文件设置Content-type

如果您确定它是一个文本文件,那么请尝试在您的curl 命令中使用的text/plain - 即使您似乎正在上传一个 jpeg 文件?但是,对于 jpeg 图像,您应该使用image/jpeg

否则对于任意二进制数据,您可以使用application/octet-stream

openBin = {'file': (fileName, open(path,'rb'), 'image/jpeg' )}

另外,也不必在代码中显式读取文件内容,requests 会为您执行此操作,因此只需传递打开的文件句柄,如上所示。

【讨论】:

  • 嘿,我确实尝试过内容类型纯文本作为标题,以及其他各种。这可以为任何类型的文件调用,所以我没有指定。下载后,纯文本仍然可以在 curl 中使用,但是在带有请求的 python 中,“image/jpeg”或“application/octet-stream”也不能。我注意到它在存储库 hasMimeType 中有一个属性,即:multipart/form-data;boundary=9f74e4d3067e4ce482bdc9e311b58d2d 有帮助吗?
  • 也感谢您提供有关阅读的提示,我之前在调试时添加了该提示。我把它拿出来
  • @awscott:服务器似乎没有正确处理多部分/表单格式的请求。我已经更新了我的答案以显示一种更简单的方法,该方法会产生与工作 curl 命令类似的请求。
  • 你是对的,那行得通!谢谢!我也按照您的建议将 Content-Type 标头设置为 application/octet-stream ,现在它可以正常工作了。
  • r = requests.put(url, data=open(path, 'rb'), headers=headers, auth=('username', 'pass')) - 如果文件是太大,流式传输而不将它们读入内存会更有意义吗?如果是,该怎么做?
猜你喜欢
  • 1970-01-01
  • 2016-02-18
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-23
相关资源
最近更新 更多