Search code examples
react-nativeblobfetcharraybuffer

Get PDF out of arraybuffer in React Native


The websocket on my server sends my react-native app an arraybuffer of a PDF and from there I'm trying to figure out how to display the PDF. I feel like rn-fetch-blob would be the answer but I'm not sure what goes where. On the browser, I just did this:

const pdfBlob = new Blob([e.data], {type: "application/pdf"})
const url = URL.createObjectURL(pdfBlob);
pdfViewer.setAttribute("src", url)

But React Native doesn't support making Blobs like that. My next attempt was doing something like this:

fetch(e.data, {
  responseType: "arraybuffer"
})
  .then(res => res.arrayBuffer())
  .then(res => res.blob())
  .then(pdfBlob => {
    const url = URL.createObjectURL(pdfBlob);
    /** ... */
  })
  .catch(e => console.error(e));

But that didn't work either. I know this guy got it working for images when his response from the server was a blob, but I don't know if it's the same thing.

I'm still super shakey on arraybuffers, blobs, fetching, etc. so any help is much appreciated.


Solution

  • Mmm this was a while ago so I'm not super sure about my own code or if it's already out of date. I remember reading something about RNFetchBlob being unnecessary with newer versions of React but here's how I did it:

    import RNFetchBlob from "rn-fetch-blob";
    const { fs } = RNFetchBlob;
    
    connection.onmessage = e => {
      if (typeof e.data === "string") {
        /* not array buffer */
      } else if (e.data.constructor === ArrayBuffer) {
        const base64 = binaryToBase64(e.data);
        const filePath = `${fs.dirs.CacheDir}/${shortid.generate()}.pdf`;
    
        RNFetchBlob.fs.createFile(filePath, base64, "base64").then(path => {
          // necessary ?
          RNFetchBlob.session("all").add(path);
        });
      }
    };
    

    I think I added the path to the session so I could delete the pdfs in bulk later on by their session id. Otherwise, I think with that path you can just pass that into the PDF component like this:

    <Pdf source={{ uri: path, cache: false }} />