skip to Main Content

I have a NextJS 14 App hosted on AWS Amplify. Everything appears to work correctly except …

I have a download button that makes a FETCH (POST) request to an API endpoint. The API endpoint takes the data in the POST request and generates a PDF file. The API then returns the PDF to the frontend and the download is triggered.

  • The implementation below works on localhost
  • The implementation below works on Vercel
  • The implementation below does not work on AWS Amplify. The PDF downloads and has the correct number of pages, but all pages are blank
const handleOnClick = async () => {
  const response = await fetch(`/api/report/download`, {
    method: "POST",
    cache: "no-store",
    body: data,
    headers: {
      "Content-Type": "application/json",
    },
  });

  if (!response.ok) {
    // ...
  }

  await response.blob().then((blob) => {
    // const url = window.URL.createObjectURL(blob);
    const newBlob = new Blob([blob], { type: "application/pdf" });
    const url = window.URL.createObjectURL(newBlob);
    const a = document.createElement("a");
    a.style.display = "none";
    a.href = url;
    a.download = `my-file.pdf`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);
  });
};

The API response when console.logged out:

ReadableStream { locked: false, state: 'readable', supportsBYOB: false }

I have read old posts on StackOverflow relating to setting "Rewrite and Redirect" rules but don’t think they relate.

Downloading a PDF file in ReactJS works locally but doesn't work on Amazon Amplify AWS

Any help would be greatly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    A shoutout to @RealDeepak, @MateenAli ...

    Turns out AWS Amplify needs the Content-Type": "application/pdf included in the API response header.

    Specifying the response content type resolved the issue on AWS amplify.

    The API Response Before:

    /api/report/download/route.ts

    return new Response(response.body, {
      status: 200,
    });
    

    The API Response After:

    /api/report/download/route.ts

    return new Response(response.body, {
      status: 200,
      headers: { ...response.headers, "Content-Type": "application/pdf" },
    });
    

  2. Check API Response Content-Type

    Content-Type: application/pdf
    

    Adjust the Fetch Implementation

    const handleOnClick = async () => {
      try {
        const response = await fetch(`/api/report/download`, {
          method: "POST",
          cache: "no-store",
          body: JSON.stringify(data), // Ensure data is properly serialized
          headers: {
            "Content-Type": "application/json",
          },
        });
    
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
    
        const blob = await response.blob();
        const url = window.URL.createObjectURL(new Blob([blob], { type: "application/pdf" }));
        const a = document.createElement("a");
        a.style.display = "none";
        a.href = url;
        a.download = `my-file.pdf`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        window.URL.revokeObjectURL(url);
      } catch (error) {
        console.error('Error downloading the file:', error);
      }
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search