6

I'm trying to render an <img> from a blob.

import React from 'react';
import { getImageBlob } from '../api/images';

class ImageViewer extends React.Component {
   state = {
     src: undefined,
     loading: true,
   }

  componentDidMount() {
    getImageBlob()
      .then((imageBlob) => {
        console.log(imageBlob);
        const urlCreator = window.URL || window.webkitURL;
        const imageUrl = urlCreator.createObjectURL(imageBlob);
        console.log(imageUrl);
        this.setState({ src: imageUrl, loading: false });
      })
      .catch((err) => {
        console.error(err);
        this.setState({ loading: false });
      });
  }

  render() {
    if (this.state.loading) {
      return 'loading';
    }

    return <img src={this.state.src} height={100} width={100} />;
  }
}


export default ImageViewer;

The output of the first console.log() is something like:

Blob(5842218) {size: 5842218, type: "application/json"}

I think the type might be why it's not rendering, but I'm not sure.

The output of the second console.log() is something like:

blob:http://localhost:3000/12bfba06-388d-48e2-8281-5ada40a662de

The getImageBlob() function is:

export const getImageBlob = () => new Promise((res, rej) => {
  client
    .get(`${IMAGES}`, {
      responseType: 'blob',
    })
    .then((resp) => {
      res(resp.data);
    })
    .catch((err) => {
      rej(Error(err.message));
    });
});

It's possible the server is sending back something incorrectly, so I can post that code if necessary.

updated with server code

This is the code which sends back the image blob.

const getImage = (imageKey) => {
  const params = {
    Bucket: process.env.S3_BUCKET,
    Key: imageKey,
  };

  return new Promise((res, rej) => {
    s3.getObject(params, (err, data) => {
      if (err) {
        rej(Error(err.message));
      } else {
        console.log(data);
        res(data);
      }
    });
  });
};

Output of console.log() on server side:

{ AcceptRanges: 'bytes',
  LastModified: 2018-08-18T18:07:39.000Z,
  ContentLength: 2101981,
  ETag: '"be594978d48fdc5964eb97ffb2c589f1"',
  ContentEncoding: 'blob',
  ContentType: 'image/jpg',
  Metadata: {},
  Body:
   <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 27 10 00 00 27 10 08 06 00 00 00 ba 4e 62 27 00 00 20 00 49 44 41 54 78 5e ec d0 01 0d 00 30 08 ... > }
Colin Ricardo
  • 16,488
  • 11
  • 47
  • 80
  • The issue is your content type. From the size of the blob it is clear that the server is doing its part properly, it is just that your client side is having issues. I believe this duplicate solves the issue of serving an image. – Travis J Aug 18 '18 at 18:55
  • Thanks for the comment. So, is `responseType: 'blob'` not the correct way to set the content type? – Colin Ricardo Aug 18 '18 at 18:57
  • @TravisJ The question you linked seems to deal solely with Node.js unless I'm missing something? – Colin Ricardo Aug 18 '18 at 18:59
  • It does primarily aim at Node.js (which you tagged here as well), however the primary reason I linked that duplicate is because `responseType` is not the correct way to set the content type, you need to indicate the `contentType` in the request header, which the duplicate covers. – Travis J Aug 18 '18 at 19:37
  • Setting the `contentType` to `image/jpeg` in the `getImageBlob()` doesn't seem to work. Should it be set to `application/json`? – Colin Ricardo Aug 18 '18 at 19:39
  • Hm, the response blob should be image/jpeg (for that type I think). Well, if the duplicate doesn't solve the issue I will reopen it. – Travis J Aug 18 '18 at 19:43
  • I've been trying to fix it since the question was posted, and I can't seem to parse a workable solution from the question you posted – especially since you mentioned the server seems to be returning data correctly. I'll update with server code just in case. – Colin Ricardo Aug 18 '18 at 19:44
  • When doing a getObject() from the S3 API, per the docs the contents of your file are located in the Body property. can you add your server console log result? – Rubel hasan Aug 18 '18 at 20:11
  • @Rubelhasan sure, updated question. – Colin Ricardo Aug 18 '18 at 20:13
  • @Rubelhasan I tried that before you deleted your answer, but it still doesn't work, and now the `Blob` object is only of size `2`. – Colin Ricardo Aug 18 '18 at 20:21
  • ok did you remove this code base `console.log(imageBlob); const urlCreator = window.URL || window.webkitURL; const imageUrl = urlCreator.createObjectURL(imageBlob); console.log(imageUrl);` on the fornt-end? – Rubel hasan Aug 18 '18 at 20:24
  • @Rubelhasan Yep, no luck – just takes way longer to load, and still doesn't work :( – Colin Ricardo Aug 18 '18 at 20:26
  • @Colin I guess you need to create a new buffer from the data.Body. `new Buffer(data.Body).toString('binary');`. and remove window.webkitURL on the front end. – Rubel hasan Aug 18 '18 at 20:33
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/178274/discussion-between-rubel-hasan-and-colin). – Rubel hasan Aug 18 '18 at 20:37

1 Answers1

0

I think it's that instead of Blob(5842218) {size: 5842218, type: "application/json"} is Blob(5842218) {size: 5842218, type: "image/jpeg"} change the type

kyun
  • 9,710
  • 9
  • 31
  • 66