2

I have created controller in Laravel which contains following code

$doc = Document::find($id);
if (Storage::disk('local')->exists($doc->path)) {
      return Storage::disk('local')->get($doc->path);
}

In my frontend I'm using javascript to programatically download the file with following code (is it ok to use blob or there is any other way to do it?)

async downloadDocument() {   
  DocService.downloadDoc(this.document.id).then((response) => {  // Service that handles ajax call
    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement("a");
    link.href = url;
    link.setAttribute("download", this.document.name);
    document.body.appendChild(link);
    link.click();
    link.remove();
  });
},

I'm able to download and see contents of txt, php files but when I try to download image, pdf, etc files are downloaded but content of the files are empty or unreadable.

Ankit.Z
  • 740
  • 8
  • 20

2 Answers2

2

If someone comes across similar issue you can do following to solve it

Laravel/backend Code:

    $path = storage_path() . '/app/' . $doc->path;
            return response()->download($path);

Define path of your file and response it with download()

Frontend Code:

    async downloadDocument() {
      axios({
        url: "/api/documents/" + this.document.id,
        method: "GET",
        responseType: "blob", // important
      }).then((response) => {
        // Service that handles ajax call
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement("a");
        link.href = url;
        link.setAttribute("download", this.document.name);
        document.body.appendChild(link);
        link.click();
        link.remove();
      });
    },
  },

Remember responseType is important, else your downloaded file(pdf, image) won't show any content.

Hope this answer can help someone.

Ankit.Z
  • 740
  • 8
  • 20
0

Use the download() method witht the proper headers instead:

return Storage::download($doc->path, basename($doc->path), [
    'Content-Description' => 'File Transfer',
    'Content-Type' => mime_content_type($doc->path),
]);

In case you want to sent the file as raw text to the client and let it decide what to do with it:

return response(Storage::disk('local')->get($doc->path))->withHeaders([
    'Content-Description' => 'File Transfer',
    'Content-Type' => mime_content_type($doc->path),
]);
shaedrich
  • 5,457
  • 3
  • 26
  • 42
  • Already tried this code but still pdf, image files are empty or unreadable – Ankit.Z Jun 15 '21 at 09:49
  • I added headers to my answer. Does that work? – shaedrich Jun 15 '21 at 09:54
  • Still downloaded files are empty. Instead of forcing download on backend is there a way to send proper content type to the frontend that can be accessed in blob. My code works in case of txt and php files because content of this files is readable whereas in case of pdf content is in binary format. – Ankit.Z Jun 15 '21 at 13:52
  • Sure, I added an alternative solution. Hope, that works – shaedrich Jun 15 '21 at 13:55
  • Doesn't work still downloaded files are empty. what is use of mime_content_type in your soln? – Ankit.Z Jun 16 '21 at 07:25
  • To determine the Content-Type dynamically. My assumption was that while text and php are both essentially text, images and PDF are not, so the browser has to be told how to handle its contents. – shaedrich Jun 16 '21 at 07:30