1

I'm trying to download a file from Django to client using GCP. Currently, the request is made from axios, the file is fetched from GCP using url from the model. This file is then downloaded and returned as a HTTP response to the client. Inside the network tab, I can see a 200 OK response and the image is visible in the preview. However, the download is not being saved to the client desktop. I would appreciate any suggestions

Download method:

def download(request, pk):
  url = Model.objects.get(id=pk).__dict__["file1"]
  storage_client = storage.Client()
  bucket = storage_client.get_bucket(setting("GS_MEDIA_BUCKET_NAME"))
  blob = storage.Blob(url, bucket)
  filename = url.rsplit("/", 1)[1]
  file_path = "temp/" + filename
  file_to_download = open(file_path, "rb")
  mime_type, _ = mimetypes.guess_type(file_path)
  response = HttpResponse(file_to_download, content_type=mime_type)
  response["Content-Disposition"] = "attachment; filename=%s" % filename
  return response 

Response headers

HTTP/1.1 200 OK
Date: Fri, 29 Oct 2021 08:01:15 GMT
Server: WSGIServer/0.2 CPython/3.9.7
Content-Type: image/jpeg
Content-Disposition: attachment; filename=default.jpg
Vary: Origin
Access-Control-Allow-Origin: http://localhost:3000
X-Frame-Options: SAMEORIGIN
Content-Length: 10994
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin

Request headers

GET /api/models/download/26/ HTTP/1.1
Connection: keep-alive
sec-ch-ua: "Chromium";v="94", "Google Chrome";v="94", ";Not A 
Brand";v="99"
Accept: application/json, text/plain, */*
sec-ch-ua-mobile: ?1
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 
Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/94.0.4606.81 Mobile Safari/537.36
sec-ch-ua-platform: "Android"
Origin: http://localhost:3000
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
George
  • 101
  • 9
  • 1
    Read https://stackoverflow.com/questions/41938718/how-to-download-files-using-axios – lucutzu33 Oct 29 '21 at 08:21
  • Thank you, however, I need the response from the server to be the file, which is then downloaded to the client. I believe by using header "Content-Disposition" = "attachment" the file should be downloaded? – George Oct 29 '21 at 08:27
  • Are you testing your request with postman? – xBurnsed Oct 29 '21 at 08:29
  • Yeah, I use postman to make the requests and the response returned is the image I need to be downloaded – George Oct 29 '21 at 08:30
  • 1
    In postman, there is a dropdown in the Send button where you can select Send and download instead. Make sure you are using this option – xBurnsed Oct 29 '21 at 08:31
  • This works inside postman, how do I make this file download on client side? – George Oct 29 '21 at 08:33
  • Have you tried in client side? IIRC it should automatically work – xBurnsed Oct 29 '21 at 08:33
  • Exactly the same request from vue, but no download. Tested on safari and chrome, same result – George Oct 29 '21 at 08:34
  • Could you please edit your post adding the headers you are using to send the request? Do not include sensitive information like tokens or similar stuff – xBurnsed Oct 29 '21 at 08:37
  • sure, request headers added – George Oct 29 '21 at 08:40

1 Answers1

1

It's a sad day for axios and content-disposition https://medium.com/@drevets/you-cant-prompt-a-file-download-with-the-content-disposition-header-using-axios-xhr-sorry-56577aa706d6

The solution will be along the lines of the following code, from the front-end:

axios({
  url: 'http://localhost:5000/static/example.pdf',
  method: 'GET',
  responseType: 'blob', // important
}).then((response) => {
  const url = window.URL.createObjectURL(new Blob([response.data]));
  const link = document.createElement('a');
  link.href = url;
  link.setAttribute('download', 'file.pdf');
  document.body.appendChild(link);
  link.click();
});
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
George
  • 101
  • 9