1

I am pretty new to using Guzzle with Laravel. I currently just use it for communication between my front-end and a seperate REST api.

I'm trying to download a file from my api but I'm not sure how to go about it. I could just specify the path to the file and directly download it but I also want to be able to stream or view it in my browser so a user can just view a word document instead of just downloading it.

Currently I'm sending a GET request from front end project (with backend to do api calls) to the api project:

$resp = $client->request('GET', env('API_BASE_URL').'/project/'.$id. '/download-report', [ 'headers' => [ 'Authorization' => 'Bearer '. session()->get('api_token') ] ]);

and in my api backend I return the file with the ->download() function.

return response()->download($report->getPath());

Can someone explain what would be the best way to approach this situation?

Solutions for both issues would be awesome, just downloading it, or actually viewing the contents of the word document.

Thanks in advance!

Cindy Meister
  • 25,071
  • 21
  • 34
  • 43
Joren vh
  • 770
  • 1
  • 6
  • 12
  • Content types for office documents can be found here: https://stackoverflow.com/questions/4212861/what-is-a-correct-mime-type-for-docx-pptx-etc – Mark Baaijens Apr 09 '19 at 07:22

1 Answers1

0

First of all, it's better to serve files with the web server (and leave PHP for "smarter" work). The idea behind it is to generate a "secure" link, that hides the real file and has an expiration timeout.

There are a few ways to do that (depends on your server: nginx, Apache or something else). A good example for nginx, with which you can just generate such link in your API, and send it to the end user through your frontend.

If you prefer to do in PHP for some reasons, just download the file to a temporary file and send it using response()->download() with corresponding headers (Content-Type) in your frontend.

$tmpFile = tempnam(sys_get_temp_dir(), 'reports_');

$resp = $client->request('GET', '...', [
    // ... your options ...
    'sink' => $tmpFile,
]);

response()->download(
    $tmpFile,
    null,
    [
        'Content-Type' => $resp->getHeader('Content-Type')[0]
    ]
)->deleteFileAfterSend(true);
Community
  • 1
  • 1
Alexey Shokov
  • 4,775
  • 1
  • 21
  • 22
  • Thanks for the reply! I'm currently just serving it as base64 data and decoding it back at the other side. Then saving it to a temp file and downloading it. I think this is kind of the same thing you're doing, right? – Joren vh Apr 11 '17 at 13:35
  • Mostly the same, but if the file is really big, you can go over the memory limit and crash. With `sink` option you write bytes directly to the file (as you receive them), so no memory overflow is possible. – Alexey Shokov Apr 12 '17 at 08:41
  • So I would advice to skip base64 encoding/decoding inside your app (between backend and frontend), to simplify design and be able to use `sink`. – Alexey Shokov Apr 12 '17 at 08:42