我正在尝试使用我的 React 应用程序使用 SAS 下载存储在 Azure Blob 存储中的文件,但遇到了问题。我有一个工作版本,它依赖于让烧瓶应用程序下载文件,然后将 blob 发送到反应应用程序以再次下载(显然不理想)。这是当前的实现:
烧瓶端点:
from azure.storage.blob import BlobServiceClient
blobService = BlobServiceClient(account_url="https://<account_name>.blob.core.windows.net/", credential=<blob_key>)
@app.route('/download')
def downloadFile():
filename = request.args.get('filename')
blob_client = blobService.get_blob_client(container='<container_name>', blob=filename)
blobObject = blob_client.download_blob()
fileObject = io.BytesIO(blobObject.readall())
return send_file(fileObject, attachment_filename=filename, as_attachment=True)
在反应中获取请求:
const getFile = (e) => {
e.preventDefault();
const filename = e.currentTarget.getAttribute('name');
axios({
url: `${serverUrl}/download?filename=${filename}`,
method: 'GET',
responseType: 'blob',
})
.then(({ data }) => {
const link = document.createElement('a');
const url = URL.createObjectURL(new Blob([data]));
link.href = url;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch(() => {
_isMounted.current && setDisplayError(true);
});
};
我希望能够让我的 React 应用程序直接从 blob 存储下载文件,但遇到了身份验证问题,以及另一个问题,即单击下载按钮将浏览器导航到 url 而不是仅仅下载文件在当前页面上的位置。这是有问题的新代码。
新的烧瓶端点:
from azure.storage.blob._shared_access_signature import BlobSharedAccessSignature
signatureService = BlobSharedAccessSignature('<account_name>', account_key='<azure_key>')
@app.route('/download')
def downloadFile():
filename = request.args.get('filename')
expiration = datetime.datetime.today() + datetime.timedelta(minutes=5)
container = '<container_name>'
key = signatureService.generate_blob(container, filename, permission='read', expiry=expiration)
data = {
'container': container,
'key': key
}
return app.response_class(
response=jsonifyWithNumPy(data),
status=200,
mimetype='application/json'
)
在反应中获取请求:
const getFile = (e) => {
e.preventDefault();
const filename = e.currentTarget.getAttribute('name');
axios
.get(`${serverUrl}/download?filename=${filename}`)
.then(({data}) => {
const url = `https://<account_name>.blob.core.windows.net/${data.container}/${filename}?${data.key}`
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch(() => {
_isMounted.current && setDisplayError(true);
});
};
这是我按照上面的反应代码生成的 URL 时得到的错误:
<Error>
<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:48c49456-001e-008b-263c-3625fd000000 Time:2021-04-20T23:23:26.1909093Z</Message>
<AuthenticationErrorDetail>Signature fields not well formed.</AuthenticationErrorDetail>
</Error>
答案 0 :(得分:0)
我尝试了您的代码来创建 blob SAS 密钥并得到相同的错误,只需尝试以下适用于我的代码来创建 blob SAS 密钥并成功访问 blob:
from azure.storage.blob import generate_blob_sas,BlobSasPermissions
from datetime import datetime, timedelta
account = ''
container = ''
blob = ''
account_key = ''
permission=BlobSasPermissions(read=True)
exp = datetime.utcnow() + timedelta(hours=1)
key = generate_blob_sas(account_name=account,container_name=container,blob_name=blob,account_key=account_key,permission=permission,expiry=exp)