12
votes

Third Party API return a "QR code image" in base64 encode,
I need save that image to User's Album.

the React-Native-Fetch-Blob maintainer gone missing, so no one answering Github Issue, createFile from React-Native-Fetch-Blob Document not working as expected(not saving image into album)

  import fetch_blob from 'react-native-fetch-blob';

  // json.qr variable are return from API

  const fs = fetch_blob.fs
  const base64 = fetch_blob.base64
  const dirs = fetch_blob.fs.dirs

  const file_path = dirs.DCIMDir + "/some.jpg"
  const base64_img = base64.encode(json.qr)

  fs.createFile(file_path, base64_img, 'base64')
  .then((rep) => { 
    alert(JSON.stringify(rep));
  })
  .catch((error) => {
    alert(JSON.stringify(error));
  });

Anyone deal with this problem before?

How to save a base64 encode Image string to User album? (as a jpg or png file)

because I fetch an API with no CORS header,
I can't debug it in Debug JS Remotely
Chrome would stop that request from happening,

I have to run that on my Android Phone to make it work
(no CORS control on real phone)

I am planing use Clipboard save base64 string,
and hardcode it in my code,
to debug what's wrong with react-native-fetch-blob createFile API

5
btw, just a simple update: I give up React Native. I built 2 app with RN 0.46 and RN 0.52. For simple app it's fine. but if it's serious Startup App. you raise money and hire people and expect it keep improving. don't use RN. reason: write interface is easy. yes. but problem is third party lib and debugging. you gonna waste a lot of time on these 2 - NamNamNam
I remember in 2017 RN is 0.52 or something like that. now it's 2019-4-29. newest version is 0.59. I think RN gonna died out slowly. Don't get me wrong. I admire people who willing to try. but unfortunately RN fail - NamNamNam
Flutter is hot these day(2019) but because I don't need to develop App right now. so I didn't try. I hope they can success. - NamNamNam

5 Answers

3
votes

You can now use only react native fetch blob to achieve this.

Simply replace RNFS.writeFile with

RNFetchBlob.fs.writeFile(file_path, image_data, 'base64')

If you wish to view file in native OS viewer you can simply put

                if (isAndroid) {
                  RNFetchBlob.android.actionViewIntent(file_path, 'application/pdf');
                } else {
                  RNFetchBlob.ios.previewDocument(file_path);
                }
19
votes

Remove data:image/png;base64, in your base64 string

var Base64Code = base64Image.split("data:image/png;base64,"); //base64Image is my image base64 string

const dirs = RNFetchBlob.fs.dirs;

var path = dirs.DCIMDir + "/image.png";

RNFetchBlob.fs.writeFile(path, Base64Code[1], 'base64')
.then((res) => {console.log("File : ", res)});

And then I solved my problem.

5
votes

I solve the problem,
turn out I forgot data:image/png;base64, at beginning of the string.
enter image description here

I remove it with following code

  // json.qr is base64 string
  var image_data = json.qr.split('data:image/png;base64,');
  image_data = image_data[1];

and then save the image file

  import fetch_blob from 'react-native-fetch-blob';
  import RNFS from 'react-native-fs';

  const fs = fetch_blob.fs
  const dirs = fetch_blob.fs.dirs      
  const file_path = dirs.DCIMDir + "/bigjpg.png"

  // json.qr is base64 string "data:image/png;base64,..."

  var image_data = json.qr.split('data:image/png;base64,');
  image_data = image_data[1];

  RNFS.writeFile(file_path, image_data, 'base64')
  .catch((error) => {
    alert(JSON.stringify(error));
  });

I wrote a blog about this

http://1c7.me/react-native-save-base64-image-to-album/

0
votes

const path = `${RNFS.PicturesDirectoryPath}/My Album`;
await RNFS.mkdir(path);
return await fetch(uri)
   .then(res => res.blob())
   .then(image => {
      RNFetchBlob.fs.readFile(uri, "base64").then(data => {
         RNFS.appendFile(`${path}/${image.data.name}`, data, "base64").catch(
            err => {
               console.log("error writing to android storage :", err);
            }
         );
      });
   });
0
votes

I got this worked in following example

import RNFetchBlob from 'rn-fetch-blob';
import Permissions from 'react-native-permissions';

 takeSnapshot = async () => {
    const currentStatus = await Permissions.check('storage');

    if (currentStatus !== 'authorized') {
      const status = await Permissions.request('storage');

      if (status !== 'authorized') {
        return false;
      }
    }

    // put here your base64
    const base64 = '';

    const path = `${RNFetchBlob.fs.dirs.DCIMDir}/test11.png`;

    try {
      const data = await RNFetchBlob.fs.writeFile(path, base64, 'base64');
      console.log(data, 'data');
    } catch (error) {
      console.log(error.message);
    }
  };