使用 React 从 Azure Blob 存储下载文件

时间:2021-04-21 00:05:43

标签: python reactjs flask azure-blob-storage

我正在尝试使用我的 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>

1 个答案:

答案 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)
相关问题