我有一个openstack对象存储容器,我正试图直接从浏览器上传文件。
根据文档here,我可以使用PUT
请求上传文件,我使用Angularjs提供的$http.put
方法执行此操作,如下所示。
$http.put(temporaryUploadUrl,
formData,
{
headers: {
'Content-Type': undefined
}
}
).then(function (res) {
console.log("Success");
});
文件上传成功,在身份验证方面没有任何问题,并为我提供201 Created
响应。但是,该文件现在在其顶部和底部包含垃圾行,因为它是使用FormData()
发送的多部分请求。
上传前的示例文件内容:
Some sample text
here is more text
here is some other text
从openstack容器中下载后的文件内容:
------WebKitFormBoundaryTEeQZVW5hNSWtIqS
Content-Disposition: form-data; name="file"; filename="c.txt"
Content-Type: text/plain
Some sample text
here is more text
here is some other text
------WebKitFormBoundaryTEeQZVW5hNSWtIqS--
我尝试FileReader
将所选文件作为二进制字符串读取,并将内容写入请求正文而不是FormData
,并且该请求适用于文本文件,但不适用于二进制文件,如XLSX
或PDF
数据完全以这种方式损坏。
答案 0 :(得分:2)
<强> 编辑: 强>
以下答案现在被认为是性能较差的解决方法As 它会将整个文件编码为base64多部分表单数据。我会 建议继续@ georgeawg的答案,如果你不是在寻找
formData
+POST
解决方案
Openstack还提供了一种不同的方法,使用FormData一次性上传一个或多个文件,如documentation中所述。有趣的是,这在谷歌搜索中从未出现过。
以下是它的简要说明。
首先,您需要使用以下python过程生成类似于tempUrl签名的签名。
import hmac
from hashlib import sha1
from time import time
path = '/v1/my_account/container/object_prefix'
redirect = 'https://myserver.com/some-page'
max_file_size = 104857600
max_file_count = 1
expires = 1503124957
key = 'mySecretKey'
hmac_body = '%s\n%s\n%s\n%s\n%s' % (path, redirect,
max_file_size, max_file_count, expires)
signature = hmac.new(key, hmac_body, sha1).hexdigest()
然后在你的javascript调用中发布到这样的容器。
var formData = new FormData();
formData.append("max_file_size", '104857600');
formData.append("max_file_count", '1');
formData.append("expires", '1503124957');
formData.append("signature", signature);
formData.append("redirect", redirect);
formData.append("file",fileObject);
$http.post(
"https://www.example.com/v1/my_account/container/object_prefix",
formData,
{
headers: {'Content-Type': undefined},
transformRequest: angular.identity
}
).then(function (res) {
console.log(response);
});
注意事项。
formData
请求中的POST
应仅包含这些内容
参数。401 Unauthorized
。答案 1 :(得分:1)
我尝试FileReader将所选文件作为二进制字符串读取,并将内容写入请求正文而不是FormData,并且该请求适用于文本文件,但不适用于二进制文件,如XLSX或PDF数据以这种方式完全损坏。
$http service的默认操作是使用Content-Type: application/json
并将对象转换为JSON strings。对于来自FileList的文件,需要覆盖默认值:
var config = { headers: {'Content-Type': undefined} };
$http.put(url, fileList[0], config)
.then(function(response) {
console.log("Success");
}).catch(function(response) {
console.log("Error: ", response.status);
throw response;
});
通过设置Content-Type: undefined
,XHR send method会自动适当地设置内容类型标题。
请注意'Content-Type': multipart/form-data
的{{3}}会增加33%的额外开销。直接发送base64 encoding和Blobs个对象效率更高。
将二进制数据作为二进制字符串发送会破坏数据,因为File会将字符串从XHR API转换为DOMSTRING (UTF-16)。避免UTF-8,因为它们是非标准和过时的。