skip to Main Content

Hi Im creating files using Jasper and now what I want to do is when user presses the button he will start to download those files, but when I tried it the response code is 200 but the popup window for the downloading on the device doesent happen. The files are saved in my folder in the app.

Here is that part of the code;

 public function generateReport(array $parameters, string $fileName, $request)
    {
        //Checking and getting formats from request
        $acceptedFormats = [
            'PDF', 'XLS', 'XLSX', 'DOCX', 'PPTX', 'CSV', 'HTML', 'RTF', 'TXT', 'XML',
            'ODT', 'ODS',
        ];

        $jsonBody = $request->getContent();
        $requestData = json_decode($jsonBody, true);
        $formats = $requestData['formats'] ?? [];

        foreach ($formats as $format) {
            if (!in_array(strtoupper($format), $acceptedFormats)) {
                throw new InvalidArgumentException('Invalid format: ' . $format);
            }
        }

        //Fetching, preparing and creating files
        $jrxmlFile = __DIR__ . 'ReportsTemplate\JasperFiles\' . $fileName . '.jrxml';

        $jasper = new PHPJasper();
        $jasper->compile($jrxmlFile)->execute();

        $jasperFile = __DIR__ . 'ReportsTemplate\JasperFiles\' . $fileName . '.jasper';
        $outputFile = __DIR__ . 'ReportsOutput\' . $fileName;

        $jasperConfig = config('jasper.db_connection');
        $options = [
            'format' => $formats,
            'params' => $parameters,
            'db_connection' => $jasperConfig
        ];


        //Where the magic happens
        $jasper->process(
            $jasperFile,
            $outputFile,
            $options,
        )->execute();



        $filePath = $outputFile . '.pdf';
        $headers = [
            'Content-Type' => 'application/pdf',
        ];
        return response()->download($filePath, $fileName, $headers);
    }

The file creation works but I can make it so the download starts, here is the api for the FE:

    export async function generateReportForOneProduct(
    id: number,
    body: { formats: string[] }
) {
    try {
        const response = await axios.post(
            `${process.env.NEXT_PUBLIC_URL}/api/product/${id}/generateReport`,
            {
                formats: body.formats.map((format) => format.toLowerCase()),
            },
        );
        return response.data;
    } catch (error) {
        console.error("Error inserting variant:", error);
        throw error;
    }
}

Any help would be great. Thanks 🙂

2

Answers


  1. You have to create a link programmatically and trigger clicking on it. After that, you can remove the link (programmatically).

    const fileURL = window.URL.createObjectURL(new Blob([response.data]))
    
    const link = document.createElement('a')
    link.href = fileURL
    link.setAttribute('download', `file_name.pdf`)
    document.body.appendChild(link)
    link.click()
    link.remove()
    window.URL.revokeObjectURL(fileURL)
    
    Login or Signup to reply.
  2. It seems like you’re trying to trigger a file download from an API call in your frontend code … However, the issue might be related to how the file is being handled in the frontend. Typically (as in any frontend app), when you receive a file from an API response, you need to handle it appropriately to initiate the download.

    You can modify your frontend code to handle the file download:

    export async function generateReportForOneProduct(id: number, body: { formats: string[] }) {
        try {
            const response = await axios.post(
                `${process.env.NEXT_PUBLIC_URL}/api/product/${id}/generateReport`,
                {
                    formats: body.formats.map((format) => format.toLowerCase()),
                },
                {
                    responseType: 'blob', // Ensure response is treated as a blob
                }
            );
    
            // Create a blob object from the response data
            const blob = new Blob([response.data], { type: 'application/pdf' });
    
            // Create a temporary URL for the blob
            const url = window.URL.createObjectURL(blob);
    
            // Create a link element
            const link = document.createElement('a');
            link.href = url;
    
            // Set the download attribute to specify the file name
            link.setAttribute('download', 'report.pdf');
    
            // Append the link to the body
            document.body.appendChild(link);
    
            // Click the link programmatically to trigger the download
            link.click();
    
            // Remove the link from the body
            document.body.removeChild(link);
    
            // Clean up the temporary URL
            window.URL.revokeObjectURL(url);
    
            return response.data;
        } catch (error) {
            console.error("Error generating report:", error);
            throw error;
        }
    }
    

    This code snippet should ensure that the response is treated as a blob, so a binary large object representing the data. Then, it creates a temporary URL for the blob and triggers a download by programmatically clicking a link with the download attribute set.

    You should adjust the MIME type and file name according to the actual file type you are downloading. Also the backend response headers must be correctly set to indicate the file type being downloaded.

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