TheGees
TheGees

Reputation: 115

Read Binary Data from blob to display Image React Native

here's the flow of what I have to do:

  1. take image with image picker for react native and get the image data in base64 (sourceData)
ImagePicker.showImagePicker(imagePickerOptions, (response) => {
    const sourceData = { uri: 'data:image/jpeg;base64,' + response.data };
});
  1. Post the sourceData.uri to a server running locally on my machine:
const data = new FormData();
data.append('receipt', {
    uri: sourceData.uri,
    type: 'image/jpeg',
    name: 'receipt'
});

const response = await fetch(SERVER_POST_ROUTE, {
    method: 'POST',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'multipart/form-data',
    },
    body: data
});

The sourceData.uri looks like this:

'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAABLKADAAQAAAABAAAA4QAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgA4QEsAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMABgYGBgYGCgYGCg4KCgoOEg4ODg4SFxISEhISFxwXFxcXFxccHBwcHBwcHCIiIiIiIicnJycnLCwsLCwsLCwsLP/bAEMBBwcHCwoLEwoKEy4fGh8uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u<…>'
  1. That's the server POST route (shortened)
router.post('/:id/receipts', (req, res) => {
  const id = req.params.id
  const expense = expenses.find((expense) => expense.id === id)

  if (expense) {
    const receipt = req.files.receipt as UploadedFile
    const receiptId = `${id}-${expense.receipts.length}`
    receipt.mv(`${process.cwd()}/receipts/${receiptId}`, (err) => {

      expense.receipts.push({
        url: `/receipts/${receiptId}`
      })
      res.status(200).send(expense)

    })

  } else {
    res.status(404)
  }
})
  1. That's what the server gets when I console.log(receipt)
{ name: 'receipt',
  data:
   <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 48 00 48 00 00 ff e1 00 58 45 78 69 66 00 00 4d 4d 00 2a 00 00 00 08 00 02 01 12 00 03 00 00 00 01 00 01 ... >,
  encoding: '7bit',
  truncated: false,
  mimetype: 'image/jpeg',
  md5: SOME_MD5_STRING,
  mv: [Function: mv] }
  1. As you see, the server moves the file to a local location receipt.mv(`${process.cwd()}/receipts/${receiptId}`)

6. MY PROBLEM: I need to access this location and turn what I get back into an image

What I am doing right now: - Use fetch to get what is at that location and extract the blob

const response = await fetch(FILE_LOCAL_URL);
const blob = await response.blob();
{ _data: 
   { size: 23296,
     offset: 0,
     blobId: 'F8F693CD-6FBB-41C8-95E3-E54EB2A82F63',
     type: 'application/octet-stream',
     name: '5b996064dfd5b783915112f5-3' } }

Now: I can't figure out how to turn this binary file into an base64 string to add to the uri of the image. That's what I tried, but obviously it does not work:

<Image 
    source={{ uri: 'data:image/jpeg;base64,' + blob._data }}
    style={{height: 120, width: 80}}/>

Any help is truly appreciated. Thanks

Upvotes: 2

Views: 8499

Answers (1)

TheGees
TheGees

Reputation: 115

Actually I solved it: to read the blob ideally you should use readAsArrayBuffer but it is not implemented in react native (read also https://forums.expo.io/t/blob-object-how-can-i-access-the-blobs-raw-data-as-an-arraybuffer/9717). But you can use readAsDataURL What I was looking for is stored in reader.result.

const response = await fetch(URL_OF_BINARY_DATA_FILE);
const blob = await response.blob();
var reader = new FileReader();
reader.onload = () => {
   console.log(reader.result);  
}
reader.readAsDataURL(blob);

Upvotes: 5

Related Questions