3

我正在尝试使用 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 正确打开和上传文件呢?

###额外细节:###

  • 当我替换files=openBindata=openBin我的字典时,我假设数据是一个字符串。我不知道这些信息是否有用。
    "file=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

4

1 回答 1

12

更新

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

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

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

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


尝试设置Content-type文件。

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

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

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

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

于 2017-12-12T22:54:35.423 回答