1

In my application I'm downloading previously stored images and pdf documents from amazon s3:

public async downloadFile(file: string): Promise<DownloadedFileType> {
    const data = await this.#s3.send(
      new GetObjectCommand({
        Bucket: process.env.AWS_BUCKET_NAME,
        Key: file,
      }),
    );

    return { stream: data.Body, name: file };
  }

Problem happens when I try to convert obtained stream in to base64 image (to send it as a "preview" to my front end):

private getBase64FromStream(
    stream: Readable,
    fileType: string,
  ): Promise<string> {
    return new Promise((resolve, reject) => {
      const data: Uint8Array[] = [];

      function onData(chunk: Uint8Array): void {
        data.push(chunk);
      }

      stream.on('data', onData);
      stream.once('end', () => {
        const result = Buffer.concat(data).toString('base64');
        const mimeType =
          fileType === 'pdf' ? 'application/pdf' : `image/${fileType}`;

        resolve(`data:${mimeType}; base64, ${result}`);

        stream.off('data', onData);
      });
      stream.once('error', reject);
    });
  }

It works fine for images (jpeg, png, etc.), but doesn't work for pdf documents. Rendering such base64 on my frontend results in error:

export function PreviewComponent({
  src,
}: IProps): JSX.Element {
  const classes = useStyles();
  const { dispatch } = useContext(AppContext);
  const onImageClick = () => {
    dispatch(openImageModalAction(src));
  };
  const onError = (e: unknown) => {
    console.log(e);
  };

  return (
    <img
      className={classes.imageWrapper}
      src={src}
      alt="preview"
      onClick={onImageClick}
      onError={onError}
    />
  );
}

With error being React's SyntheticBaseEvent:

type: "error"
_reactName: "onError"

I have no clue what I'm doing wrong. I know you can convert pdf files to base64. Any help will be greatly appreciated.

yms
  • 10,361
  • 3
  • 38
  • 68
Furman
  • 2,017
  • 3
  • 25
  • 43

1 Answers1

0

You are using an <img> tag for displaying your PDF, but it happens that PDF are not images, so the img tag will NOT support it.

MDN confirms that PDF is not on the list of supported formats for the img tag:

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img

Try using an embed or iframe tags instead as indicated here:

How to display PDF file in HTML?

See an example for react here:

https://stackblitz.com/edit/react-ts-pgvu9y?file=index.tsx

class App extends Component<AppProps, AppState> {
  constructor(props) {
    super(props);
    this.state = {
      name: 'React'
    };
  }

  render() {
    return (
      <div>
          Displaying a PDF file with React<br/>

          embed tag works<br/>
          <embed src="https://www.inkwelleditorial.com/pdfSample.pdf" width="800px" height="400px" />

          img tag does not work<br/>
          <img src="https://www.inkwelleditorial.com/pdfSample.pdf" width="800px" height="400px" />
        
      </div>
    );
  }
}
yms
  • 10,361
  • 3
  • 38
  • 68
  • I'm not trying to display PDF file in tag, I'm trying to display base64 encoded image (created from pdf file). – Furman May 18 '21 at 22:17
  • @Furman Your code says: return ( – yms May 19 '21 at 18:17
  • Sorry but I don't understand - how does it works in case of base64 string made from regular images (png, jpg, etc.)? I know you can convert pdf to base64 (https://stackoverflow.com/questions/39616302/convert-pdf-file-into-base64-string-with-javascript?rq=1). My question is what I did wrong so it don't work in form I posted. – Furman May 19 '21 at 18:49
  • I added an example of using and img tag vs using an embed tag to display a PDF. You will see that the embed tag works while the img tag does not. As I mentioned before, base64 is irrelevant in your problem. I also offered a link to the documentation of the img tag, you can see for yourself that PDF is not supported. I am not sure what else I can do to help. – yms May 20 '21 at 00:48
  • Problem is, that embed tag doesn't work either. That's why I still suspect that document is badly converted to base64, but I can't find source of problem – Furman May 24 '21 at 19:08
  • Just out of curiosity I updated my sample with an embed tag + a data url, and it does work. https://stackblitz.com/edit/react-ts-pgvu9y So you are right, your algorithm for converting to base64 seems to have a problem. – yms May 29 '21 at 03:29