download file in react

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
# Mastering File Downloads in React: Bridging the Gap Between Laravel APIs and Frontend Experience As developers, we often encounter a frustrating scenario: an API endpoint works perfectly when tested with tools like Postman or directly in a browser, but implementing the download functionality within a modern frontend framework like React proves tricky. This is especially true when dealing with file downloads served from backend systems like Laravel. This post will dive deep into why your standard `fetch` request might fail to trigger a download in React and provide you with the correct, robust method to handle binary file streams. We will bridge the gap between your Laravel backend and your React frontend effectively. ## The Core Problem: JSON vs. Binary Responses The issue you are facing stems from how the server responds versus how the frontend is interpreting that response. In your Laravel controller: ```php public function pdfDownload($id){ $pdf = Cv::findOrfail($id); return Storage::download('public/pdf/' . $pdf->pdf); // This returns a file stream } ``` When you call `Storage::download()`, Laravel sets the appropriate HTTP headers (like `Content-Type` and `Content-Disposition`) to instruct the browser to download the file. The response body is raw binary data, not JSON. In your initial React attempt: ```javascript fetch(' http://127.0.0.1:8000/api/file/pdf/' + id, { method: 'get', headers: { /* ... */ } }).then((res) => res.json()); // <-- Problem here! ``` By calling `res.json()`, you are telling the browser to parse the response body as a JSON string. Since the response is raw file data, this parsing fails, and the download mechanism is never triggered because React doesn't receive the necessary stream information to initiate a file save dialogue. ## The Solution: Handling Binary Streams with `fetch` and Blobs To successfully download a file in React, you must treat the response as a stream of raw data (a `Blob`) rather than trying to parse it as JSON. We need to read the response body as an array buffer and then create a temporary URL that the browser can use to initiate the download. Here is the complete, corrected approach for downloading files in React: ```javascript const downloadPdf = async (id) => { try { // 1. Fetch the file response, expecting a Blob const response = await fetch(`http://127.0.0.1:8000/api/file/pdf/${id}`, { method: 'GET', headers: { Accept: 'application/octet-stream' // Request binary data } }); // 2. Check if the request was successful if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } // 3. Read the response body as a Blob (Binary Large Object) const blob = await response.blob(); // 4. Create a temporary URL for the Blob const url = window.URL.createObjectURL(blob); // 5. Create a temporary link element to trigger the download const a = document.createElement('a'); a.href = url; // Set the filename (optional, but good practice) // Assumes you know the file name or can derive it from your ID logic a.download =