0

I'm stuck with this issue for a few days now.

I made a React native app, that retrieved all restaurant dishes and images from a server. Now my customer wants me to add an offline mode to it.

My idea is to store all data on the phone, in the SQLite database, and use the local database to view all the Data, including all images. Every time the user starts the app it refreshes the data on the phone so it's always updated as well.

But I can't figure out to save the Image as a blob from the web URL.

I know how to convert images to Blob and from Blob to base64 but when I call the function I do not get the correct value back. If I enable the console log and check the result of the function, it prints everything it should.

But when I got the returned value it was garbage or empty, depending on using await and async or not.

This a simple function to turn URL image to blob and then to base64. Console.log is fine but returning does not get me the result.

export const convertImageToBase64 = async (imgUrl) => {
  const fr = new FileReader();
  await fetch(imgUrl).then((response) => {
    response.blob().then((blob) => {
      fr.readAsDataURL(blob);
      fr.onload = () => {
        console.log(fr.result);
      };
    });
  });
};

EDIT: It's not a problem to get the image converted, the problem is to get it back as converted in the return statement so i can put it in the query.

This is the Part in my Code where i need to put in my converted Image.

db.transaction((tx) => {
    tx.executeSql(
      "CREATE TABLE items (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, img BLOB, done INTEGER)"
    );
  });

  db.transaction(function (tx) {
    result.map(async (item) => {
      tx.executeSql(
        "INSERT INTO items (name,img,done) VALUES (?,?,?)",
        [
          item.name,
          convertImageToBase64(imgUrl),     //<-- Something like that
          item.done,
        ]
        (tx, results) => {
          console.log('Results', results.rowsAffected);
        }
      );
    });
  });

Anyone can help with this?

I need a solution to get the converted data to put it in the database.

EDIT: Getting closer.

turned out the problem is the async in my map method. Here i got it as blob or base64, works fine.

`result.map(async (item) => {

      console.log(await convertImageToBase64(imgUrl));
      //const objectURL = URL.createObjectURL(await convertImageToBase64(config.produktBilderMärkte+item.bild));
    })`

But here in my Insert to table method Its noch working. i got empty resultset, and without the async i got null in my img field in the table, where the other values are good.

`result.map(async (item,index) => {

      tx.executeSql(
        "INSERT INTO markets (name,imgage,done) VALUES (?,?,?)",
        [
          item.name,
          await convertImageToBase64(imgUrl),
          item.done,
        ]
      );
    });`
David
  • 1
  • 1
  • 2

1 Answers1

0

Use XMLHttpRequest API instead of Fetch API as below :


function blobToBase64(blob) {
  return new Promise((resolve, _) => {
    const reader = new FileReader();
    reader.onloadend = () => resolve(reader.result);
   return  reader.readAsDataURL(blob);
  });
}


const convertImageToBase64 = async (imgUrl) => {


  const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function (e) {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", imgUrl, true);
    xhr.send(null);
  });
  

  const base64 =  await blobToBase64(blob)

  console.log({base64, blob})
  
};


convertImageToBase64("https://randomuser.me/api/portraits/men/4.jpg")

Fiston Emmanuel
  • 4,242
  • 1
  • 8
  • 14
  • Hi @Fiston As expected, the Base64 Value is what i get in your and also in my function (to big to show here) And the Error below is what i got as return value. LOG {"_data": {"__collector": {}, "blobId": "e68a30b9-0182-4a04-8374-6430f5fc9dec", "offset": 0, "size": 11957}} ERROR There was a problem sending log messages to your development environment [PrettyFormatPluginError: undefined is not a function] this part of your code is what a call as return statement `return await blobToBase64(blob)` – David May 03 '23 at 16:11
  • It seems that you are geting base64 and BLOB data. You should ignore the extra error message related to the Prettier Code formater. – Fiston Emmanuel May 03 '23 at 19:59
  • But it's not working as image. I'll check this again and try. Thanks for pointing out. – David May 04 '23 at 06:41
  • i tryed to save that file as blob in database, but the value in database is null. Any idea? – David May 04 '23 at 06:52
  • I edited my first Post. So the real question here is how can i get `db.transaction(function (tx)` with async to work?? – David May 04 '23 at 07:39
  • Sorry I meant how get i `tx.executeSql` work async – David May 04 '23 at 08:49
  • I recommend keeping image data as base64, not BLOB. it easier to retrieve from the database and show in UI with – Fiston Emmanuel May 04 '23 at 13:54
  • Yes i use the base64 data to store in database. Finally got it to work, I used a callback function that way the data was still there when i finished converting. The reason for getting empty array whas just that. – David May 05 '23 at 06:43
  • Cool. Glad you figure it out! Happy hacking! – Fiston Emmanuel May 05 '23 at 12:55