How to get base64 of photos:// path images? - react-native

In my project I am retrieving gallery's albums using react-native-photos-framework which giving me gallery's album. Then using those album object I am fetching images of that particular album, which returning assets array. Those assets contains uri which look like this :
"photos://C5E8291B-09C6-2231-856D-989D929392FA2/L0/001"
How I can get the base64 string of that image.
I tried to get using react-native-image-base64 and react-native-fs but none of working.
Here is a code in which I used react-native-image-base64 :
const base64 = await ImgToBase64.getBase64String("photos://C5E8291B-09C6-2231-856D-989D929392FA2/L0/001");
But, this giving me following error :
JSON value '' of type NSNull cannot be converted to NSString
Here is code using react-native-fs :
const base64 = await RNFS.readFile('photos://C5E8291B-09C6-2231-856D-989D929392FA2/L0/001','base64');
Above code giving me this error :
"ENOENT: no such file or directory, open 'photos://C5E8291B-09C6-2231-856D-989D929392FA2/L0/001'"
Please help me how to solve !!!

Related

How to convert asset-library:// to file:// in react-native expo?

I'm using expo to build a cross-platform application. In my app, I have a screen where user can select images or videos to upload.
When I use expo-image-picker to select image it gives me an object which its uri starts with file:/// and I can use this uri to display the image.
When I use expo-image-picker-multiple to select multiple images it gives me objects and the uri starts with asset-library:// and I can't use this uri to display the content of it nor send it to server.
How can I convert this asset-library:// to file://? What keyword should I use to get better results when doing google search on this problem or which tool should I use? I can't really find a proper solution to this one. This occurs on IOS devices.
Thanks!
[EDIT]
here is my code
var assetUri = 'asset-library://....'
var tempDir = `${FileSystem.cacheDirectory}${Math.random().toString(36).substring(7)}.jpg`
FileSystem.copyAsync({
from: assetUri,
to: tempDir
})
try {
var assetResult = await FileSystem.readAsStringAsync(tempDir, {
encoding: FileSystem.EncodingType.UTF8
})
console.log(assetResult)
}
catch(e) {
console.log(e)
}
File 'file:///var/mobile/Containers/Data/Application/0E-FC42-4630-B3C7-537D5EFB7D1F/Library/Caches/ExponentExperienceData/ichardexpohong/gwmke.jpg' could not be read.
I wanted only the filename so i used
let filename= result.assets[0].uri.split('/')[result.assets[0].uri.split('/').length-1]
so maybe if the path after both asset-library and file:// are the same you can use
take away the asset-library:// then replace it with file://
let uri='file://' + object.uri.split('asset-library://')[1]
hope it helps

Adobe PDF Embed API Save Content To Base64

Using Adobe PDF Embed API, you can register a callback:
this.adobeDCView = new window.AdobeDC.View(config);
this.adobeDCView.registerCallback(
window.AdobeDC.View.Enum.CallbackType.SAVE_API, (metaData, content, options) => {
})
Content is according to the docs here: https://www.adobe.io/apis/documentcloud/dcsdk/docs.html?view=view
content: The ArrayBuffer of file content
When I debug this content using chrome inspector, it shows me that content is a Int8Array.
Normally when we upload a pdf file, the user selects a file and we read as dataURI and get base64 and push that to AWS. So I need to convert this PDF's data (Int8Array) to Base64, so I can also push it to AWS.
Everything I have found online uses UInt8Array to base64, and I don't understand how to go from Int8Array to UInt8Array. I would think you can just add 128 to the signed int to get a ratio between 0-256, but this doesn't seem to work.
I have tried using this:
let decoder = new TextDecoder('utf8');
let b64 = btoa(decoder.decode(content));
console.log(b64);
But I get this error:
ERROR DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
Please help me figure out how to go from Int8Array to Base64.
I use the function in this answer.
For Embed API, use the "content" parameter from the save callback as the input to the function.
You can see a working example at this CodePen. The functional part is below.
adobeDCView.registerCallback(
AdobeDC.View.Enum.CallbackType.SAVE_API,
function (metaData, content, options) {
/* Add your custom save implementation here...and based on that resolve or reject response in given format */
var base64PDF = arrayBufferToBase64(content);
var fileURL = "data:application/pdf;base64," + base64PDF;
$("#submitButton").attr("href", fileURL);
/* End save code */
return new Promise((resolve, reject) => {
resolve({
code: AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
data: {
/* Updated file metadata after successful save operation */
metaData: { fileName: urlToPDF.split("/").slice(-1)[0] }
}
});
});
},
saveOptions
);

How to get file name from asset uri in React Native

I want to be able to get the file name and type from an image from my camera roll. Here is the link to the file:
"assets-library://asset/asset.JPG?id=ED7AC36B-A150-4C38-BB8C-B6D696F4F2ED&ext=JPG"
How do I extract the file name and mime type from here. I'm particularly interested in the mime type because I can generate random names but I need to be correct on the type when uploading the file.
Right now, there is a really good package to handle this called expo-asset-utils.
import AssetUtils from 'expo-asset-utils';
const { localUri, width, height } = await AssetUtils.resolveAsync(uri);
// localUri now contains the converted URI to a 'file://' URI
try out npm i expo_file_name
import {getFileName} from 'expo_file_name'
const uri = //the value for the uri goes here
const fileName = getFileName(uri);
//the name of the file is then stored in the fileName variable

react-native FormData upload does not send the right data

I've been looking through all the questions I could find but it looks like nobody had my problem.
I'm running react-native 39 and I want to upload an image. It looks like that it is possible to upload it using FormData.
/**
* Polyfill for XMLHttpRequest2 FormData API, allowing multipart POST requests
* with mixed data (string, native files) to be submitted via XMLHttpRequest.
*
* Example:
*
* var photo = {
* uri: uriFromCameraRoll,
* type: 'image/jpeg',
* name: 'photo.jpg',
* };
*
* var body = new FormData();
* body.append('authToken', 'secret');
* body.append('photo', photo);
* body.append('title', 'A beautiful photo!');
*
* xhr.open('POST', serverURL);
* xhr.send(body);
*/
Using the method I just get [object Object] in the body of the request.
Using fetch instead of xhr I get some data but now that I would expect, there's no image that I can get from the server
The problem is that the Form has no idea about what the information stored in the object that you are trying to encode means, so it will not fetch the picture data from the device, and instead, just figure out the 'proper' representation that the photo object might have, and that is usually a string. In this case [object Object]. Of course, that won't be accepted by your server. In fact this happens to all non-primitive types of JavaScript. You should use JSON.stringify(photo) to convert it to a JSON string first.
Instead, what you can try is to retrieve the image data from the camera roll in a format that FormData can understand, for instance, a string that encodes your image in base64. This is not a functionality that comes with React Native, but a quick search retrieved some promising packages. Maybe have a look at:
react-native-image-to-base64
react-native-upload-from-camera-roll
this post
JS.coach
react-native-fs
Then, once you have your image in base64 format, you can do the following:
var photo = {
data: myBase64Data,
type: 'image/jpeg',
name: 'photo.jpg',
};
var body = new FormData();
body.append('authToken', 'secret');
body.append('photo', JSON.stringify(photo));
body.append('title', 'A beautiful photo!');
xhr.open('POST', serverURL);
xhr.send(body);
Hope that helps.
If you guys are still looking for the answer why you cannot see that in Network tabs in React Native, here is an answer.
This is because you use a snippet to make this Networking tab working in debuggers.
GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;
Add also the line below, and it will enable FormData normal behavior.
GLOBAL.FormData = GLOBAL.originalFormData || GLOBAL.FormData
You should end up with following:
GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;
GLOBAL.FormData = GLOBAL.originalFormData || GLOBAL.FormData;
It worked for me.

Is there a gulp plugin to compile files contents to base64?

I have several html templates I require to "compile" and convert to base64 format. By compile I mean injecting JS and CSS inline, and then converting it to base64 format.
I tried gulp-base64 but that only works for images in CSS. Any ideas?
Edit: I just got an idea that maybe I could use gulp-foreach to process each file individually and then use a Buffer to convert each file's content's to base64 format. I know I could do something like:
> console.log(new Buffer("Hello World").toString('base64'));
SGVsbG8gV29ybGQ=
> console.log(new Buffer("SGVsbG8gV29ybGQ=", 'base64').toString('ascii'))
Hello World
But I'm not really sure how to do it since I don't understand quite well how file streams (I think it's called vinyl) work yet in gulp. Any help would be greatly appreciated.
I found your question while looking for a solution to the same problem. Your suggestion to use gulp-foreach led me to a solution, although I didn't use that package:
// import the appropriate plugins
//
const each = require('gulp-each');
const htmlToJs = require('gulp-html-to-js');
// I'm compiling a couple of small PDF files
//
gulp.task('compile:pdf', () =>
gulp.src('./files/**/*.pdf')
// use gulp-each to iterate over the files & convert the
// files to a base64-encoded data URL
//
.pipe(each((content, file, callback) => {
const output = `data:application/pdf;base64,${new Buffer(content).toString('base64')}`;
// the first arg in this callback is the error; the second
// is the content to pass along via the stream
//
callback(null, output)
}))
// use gulp-html-to-js to convert the data URL to a JS module
// which can be imported
//
.pipe(htmlToJs())
// and set the destination...
//
.pipe(gulp.dest('./client/modules/helpers/files'))
);
The end result is a JS file with contents that look like this:
'use strict';
module.exports = 'data:application/pdf;base64,... base64 encoded string...';