skip to Main Content

I am new to react, trying to get pre-signed url(s3) which is returned from the API and invoke the pre-signed URL to render the PDF on browser.

I could see two calls on network tab, one call returns 308 and other call returns 200 with response.but not sure why I am not able to get the pre-resigned URL from response, tried response.json and response.text.

How to get the response from the second call (with response status 200) or how to make sure only one call is fired?

How to render the pdf on the browser using iframe or the best way to render pdf?
I did try with hardcoded pre-signed url, it does download the pdf but does not render in iframe.

Thanks for your help in advance. below is the code snippet.

const refIframe = useRef(null)
const [data, setData] = useState(null)


useEffect(() => {
   let url =  "http://127.0.0.1:5000/files/1233"
   const fetchData = async () => { fetch(url, {
        method: 'GET',
        mode: 'no-cors', // 'cors' by default
        headers: {
            "Access-Control-Allow-Origin": "*",
            'Content-Type': 'text/html',}
        }).then(response => {
            return response.text()
        }).then(data =>
            setData(data)
        );
    }
    fetchData();
    refIframe.current.setAttribute('src', data);
}, []);


return (
    <div>
        <iframe ref={refIframe} allowFullScreen title={'PDF Viewer'} />
    </div>
)

2

Answers


  1. your mistake was accessing the data directly after setData.
    the value of data will change after rendering.
    that’s why the value of data remains null.
    if you want to use the fetched value, you need to use the data passed as an argument inside the then.

      const fetchData = async () => { fetch(url, {
            method: 'GET',
            mode: 'no-cors', // 'cors' by default
            headers: {
                "Access-Control-Allow-Origin": "*",
                'Content-Type': 'text/html',}
            }).then(response => {
                return response.text()
            }).then(data =>
                refIframe.current.setAttribute('src', data)
            );
        }
    
    Login or Signup to reply.
  2. You need to GENERATE a presigned URL from S3 after for the desired object and then use it on your frontend. You can have your BE do this & return the signed url in api response.

    With NodeJS as your backend, you can do it like this in your /files/1233 api route to make a request to s3 to generate one and return the response you received.

    const params = {
        Bucket: "bucketName",
        Key: "objectKey",
        Expires: "expirationTime in seconds",
    };
    
    s3.getSignedUrl("getObject", params, (err, preSignedUrl) => {
        if (err) {
            console.error("error generating presigned URL:", err);
            res.status(500).json({ error: "internal server error" });
        } else {
            res.json({ preSignedUrl });
        }
    });
    

    Now on the frontend, you will be able to access/render the content of the URL created by S3.

    Make sure you have right bucket policy and permissions to access the bucket.

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