简体   繁体   中英

Download File from Azure Blob Storage Using React

I am trying to download a file stored in Azure Blob Storage with my react app using SAS and am running into issues. I have a working version that relies on having the flask app download the file, then sending the blob to the react app to be downloaded again (obviously not ideal). Here's the current implementation:

flask endpoint:

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)

get request in react:

  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);
      });
  };

I would like to be able to just have my react app download the file direct from blob storage, but am running into authentication issues, along with another issue where clicking the download button navigates the browser to the url rather than just downloading the file at the location while staying on the current page. Here is the new code with the issues.

new flask endpoint:

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'
  )

get request in react:

  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);
      });
  };

This is the error I get when I follow the URL generated by the above react code:

<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>

I tried your code to create a blob SAS key and get the same error, just try the code below that works for me to create a blob SAS key and access a blob successfully:

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM