skip to Main Content

So I am trying to download a pdf file that is stored in my uploads directory within the public folder. I am using a react frontend and a laravel backend. Here is how I am handling the logic in the frontend

const downloadFile = async (attachmentName) => {
        try {
            const response = await fetch(`/attachments/${attachmentName}`);
            
            // Check if the response is OK
            if (!response.ok) {
                throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
            }
            
            // Create a blob URL for the file content
            const url = window.URL.createObjectURL(await response.blob());
            
            // Create a temporary link element to trigger the download
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', attachmentName);
            
            // Append the link to the document body and trigger the download
            document.body.appendChild(link);
            link.click();
            
            // Clean up
            document.body.removeChild(link);
            window.URL.revokeObjectURL(url);
        } catch (error) {
            console.error('Error downloading attachment:', error);
        }
    }
//Some more Code

<a href="#" onClick={() => downloadFile(job.attachments)}>
                             
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#b72424" class="bi bi-file-earmark-pdf-fill" viewBox="0 0 16 16">
        <path d="M5.523 12.424q.21-.124.459-.238a8 8 0 0 1-.45.606c-.28.337-.498.516-.635.572l-.035.012a.3.3 0 0 1-.026-.044c-.056-.11-.054-.216.04-.36.106-.165.319-.354.647-.548m2.455-1.647q-.178.037-.356.078a21 21 0 0 0 .5-1.05 12 12 0 0 0 .51.858q-.326.048-.654.114m2.525.939a4 4 0 0 1-.435-.41q.344.007.612.054c.317.057.466.147.518.209a.1.1 0 0 1 .026.064.44.44 0 0 1-.06.2.3.3 0 0 1-.094.124.1.1 0 0 1-.069.015c-.09-.003-.258-.066-.498-.256M8.278 6.97c-.04.244-.108.524-.2.829a5 5 0 0 1-.089-.346c-.076-.353-.087-.63-.046-.822.038-.177.11-.248.196-.283a.5.5 0 0 1 .145-.04c.013.03.028.092.032.198q.008.183-.038.465z"/>
        <path fill-rule="evenodd" d="M4 0h5.293A1 1 0 0 1 10 .293L13.707 4a1 1 0 0 1 .293.707V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2m5.5 1.5v2a1 1 0 0 0 1 1h2zM4.165 13.668c.09.18.23.343.438.419.207.075.412.04.58-.03.318-.13.635-.436.926-.786.333-.401.683-.927 1.021-1.51a11.7 11.7 0 0 1 1.997-.406c.3.383.61.713.91.95.28.22.603.403.934.417a.86.86 0 0 0 .51-.138c.155-.101.27-.247.354-.416.09-.181.145-.37.138-.563a.84.84 0 0 0-.2-.518c-.226-.27-.596-.4-.96-.465a5.8 5.8 0 0 0-1.335-.05 11 11 0 0 1-.98-1.686c.25-.66.437-1.284.52-1.794.036-.218.055-.426.048-.614a1.24 1.24 0 0 0-.127-.538.7.7 0 0 0-.477-.365c-.202-.043-.41 0-.601.077-.377.15-.576.47-.651.823-.073.34-.04.736.046 1.136.088.406.238.848.43 1.295a20 20 0 0 1-1.062 2.227 7.7 7.7 0 0 0-1.482.645c-.37.22-.699.48-.897.787-.21.326-.275.714-.08 1.103"/>
    </svg>

                             
    {getAttachmentName(job.attachments)}
</a>

And here is my backend logic
Routes File

Route::get('/attachments/{attachment}', [AttachmentController::class, 'show'])->name('attachments.show');

Controller

{
    public function show($attachment)
    {
        // Check if the file exists
        if (!Storage::disk('public')->exists($attachment)) {
            abort(404); // Or return a suitable error response
        }

        // Retrieve the file contents
        $fileContents = Storage::disk('public')->get($attachment);

        // Return the file as a response with the appropriate headers
        return response($fileContents, 200)
            ->header('Content-Type', 'application/pdf')
            ->header('Content-Disposition', 'attachment; filename="' . basename($attachment) . '"');
    }
    
}

So for some reason. On download the file is downloading but the file is corrupted. Also it doesn’t contain anywhere near the total number of bytes that it should contain

So what could be the issue?

2

Answers


  1. Chosen as BEST ANSWER

    I guess the issue is with how I was handling the request on the frontend. Because it wasn't hitting the backend. Since I was not using axiosClient. I also added a removeUploadsPrefix function to remove the 'uploads/' prefix from the file name as it was raising an error.

    const removeUploadsPrefix = (fileName) => {
       return fileName.replace(/^uploads//, '');
    };    
    const downloadFile = async (attachmentName) => {
            attachmentName = removeUploadsPrefix(attachmentName);
          
            try {
              setLoading(true);
              const response = await axiosClient.get(`/attachments/${attachmentName}`, {
                responseType: 'blob',
              });
          
              // Check if the response status is 200 (OK)
              if (response.status !== 200) {
                throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
              }
          
              // Create a link to download the file
              const url = window.URL.createObjectURL(new Blob([response.data]));
              const link = document.createElement('a');
              link.href = url;
              link.setAttribute('download', attachmentName); // or use a custom file name
              document.body.appendChild(link);
              link.click();
              document.body.removeChild(link);
          
              console.log('Download successful');
            } catch (error) {
              console.error('Error downloading file:', error);
              setErrors('Failed to download file');
            } finally {
              setLoading(false);
            }
          };
    

    And then on the backend I add back the 'uploads/' prefix.

        public function show($attachment)
        {
            // Adjust the attachment path to include the 'uploads/' directory
            $attachmentPath = 'uploads/' . $attachment;
    
            // Log the attachment path
            Log::info('Attempting to retrieve attachment:', ['attachment' => $attachmentPath]);
    
            // Check if the file exists
            if (!Storage::disk('public')->exists($attachmentPath)) {
                Log::error('File not found:', ['attachment' => $attachmentPath]);
                abort(404, 'File not found'); // Or return a suitable error response
            }
    
            // Retrieve the file contents
            $fileContents = Storage::disk('public')->get($attachmentPath);
    
            // Return the file as a response with the appropriate headers
            return response($fileContents, 200)
                ->header('Content-Type', 'application/pdf')
                ->header('Content-Disposition', 'attachment; filename="' . basename($attachmentPath) . '"');
        }
    

  2. More prominent may is to add download attribute to anchor.

    <a href="/attachments/${job.attachments}" download={true}>
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#b72424" class="bi bi-file-earmark-pdf-fill" viewBox="0 0 16 16">
            <path d="M5.523 12.424q.21-.124.459-.238a8 8 0 0 1-.45.606c-.28.337-.498.516-.635.572l-.035.012a.3.3 0 0 1-.026-.044c-.056-.11-.054-.216.04-.36.106-.165.319-.354.647-.548m2.455-1.647q-.178.037-.356.078a21 21 0 0 0 .5-1.05 12 12 0 0 0 .51.858q-.326.048-.654.114m2.525.939a4 4 0 0 1-.435-.41q.344.007.612.054c.317.057.466.147.518.209a.1.1 0 0 1 .026.064.44.44 0 0 1-.06.2.3.3 0 0 1-.094.124.1.1 0 0 1-.069.015c-.09-.003-.258-.066-.498-.256M8.278 6.97c-.04.244-.108.524-.2.829a5 5 0 0 1-.089-.346c-.076-.353-.087-.63-.046-.822.038-.177.11-.248.196-.283a.5.5 0 0 1 .145-.04c.013.03.028.092.032.198q.008.183-.038.465z"/>
            <path fill-rule="evenodd" d="M4 0h5.293A1 1 0 0 1 10 .293L13.707 4a1 1 0 0 1 .293.707V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2m5.5 1.5v2a1 1 0 0 0 1 1h2zM4.165 13.668c.09.18.23.343.438.419.207.075.412.04.58-.03.318-.13.635-.436.926-.786.333-.401.683-.927 1.021-1.51a11.7 11.7 0 0 1 1.997-.406c.3.383.61.713.91.95.28.22.603.403.934.417a.86.86 0 0 0 .51-.138c.155-.101.27-.247.354-.416.09-.181.145-.37.138-.563a.84.84 0 0 0-.2-.518c-.226-.27-.596-.4-.96-.465a5.8 5.8 0 0 0-1.335-.05 11 11 0 0 1-.98-1.686c.25-.66.437-1.284.52-1.794.036-.218.055-.426.048-.614a1.24 1.24 0 0 0-.127-.538.7.7 0 0 0-.477-.365c-.202-.043-.41 0-.601.077-.377.15-.576.47-.651.823-.073.34-.04.736.046 1.136.088.406.238.848.43 1.295a20 20 0 0 1-1.062 2.227 7.7 7.7 0 0 0-1.482.645c-.37.22-.699.48-.897.787-.21.326-.275.714-.08 1.103"/>
        </svg>
        
        {getAttachmentName(job.attachments)}
    </a>
    

    download attribute will prevent browser from reloading.

    If download attribute don’t work, than you can use target="_blank" instead.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search