How to read an Image file from camera roll in react-native? I tried reading a file using react-native-fs You can find the issue I am facing using this link.
I assume you already know how to select images from your CameralRoll, simply use the CameraRoll API from react-native module. If this is the way you select images, then your image uri should look like this: asset-library://asset/...
Then, you should probably use react-native-fetch-blob module:
npm install --save react-native-fetch-blob
and
react-native link
In the file where your uploadImage function is defined (I assume you use firebase as your backend because I saw that in your other question):
import RNFetchBlob from 'react-native-fetch-blob';
const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;
function uploadImage(photo) {
const ref = firebase.storage().ref('path/to/destination');
let photoBlob = null;
let imageFile = RNFetchBlob.wrap(photos[i]);
Blob.build(imageFile, { type: 'image/jpg' })
.then((blob) => {
photoBlob = blob;
return ref.put(blob, { contentType: 'image/jpg' });
})
.then(() => photoBlob.close())
.catch((error) => console.log(error));
}
All set. But if you're not using CameraRoll to select pictures (uri will look different), it is ok, simply pass the path of the photo you want to upload to this function and leave everything else the same
Related
Currently, I'm trying to load my model with this function:
const loadModel = async () => {
const modelJSON = require('../assets/models/model.json');
const modelWeights = require('../assets/models/group1-shard.bin');
const model = await tf
.loadLayersModel(bundleResourceIO(modelJSON, modelWeights))
.catch((e) => {
console.log('Error', e);
});
return model;
};
But when I try to require('../assets/models/group1-shard.bin) react-native says that it is "Unable to resolve module ../assets/models/group1-shard.bin", it also says that the file doesn't exist...
My file structure with the group1-shard.bin file:
This is the full error message:
I think if your code is in App.js you could have used the path ./assets/... instead, and also consider adding the bin files in your metro resolver.assetExts array.
I am using react-native-image-to-pdf library to convert images to pdf in my react native app. from https://www.npmjs.com/package/react-native-image-to-pdf
var photoPath = ['https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&h=350','https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&h=350'];
const myAsyncPDFFunction = async () => {
try {
const options = {
imagePaths: photoPath,
name: 'PDFName',
};
const pdf = await RNImageToPdf.createPDFbyImages(options);
console.log(pdf.filePath);
} catch(e) {
console.log(e);
}
}
but this is giving error Error: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
I have also tried giving path as ['./assets/a.png', './assets/b.png']
but still getting same error
Based on the usage example, your photoPath needs to be a local file path and not a remote path.
My recommendation is to first use rn-fetch-blob to download the remote image to the device, and then pass your new local image path to react-native-image-to-pdf. Something like:
RNFetchBlob
.config({
// add this option that makes response data to be stored as a file,
// this is much more performant.
fileCache : true,
})
.fetch('GET', 'http://www.example.com/file/example.png', {
//some headers ..
})
.then(async (res) => {
// the temp file path
console.log('The file saved to ', res.path())
const options = {
imagePaths: [res.path()],
name: 'PDFName',
};
const pdf = await RNImageToPdf.createPDFbyImages(options);
})
from file path remove the text 'file://; with empty string('').
const options = {
imagePaths: [uri.replace('file://', '')],
name: 'FileName',
quality: .9, // optional compression paramter
};
replace('file://', '') it's work for me
i need share local image on react native app, use react-native share and react-native-fs. Image is in local folder in root app named 'images'. How to share this image. Do i need copy or move image to temp and use that image for getting absolute path.
This is my code. rnfs.movefile don't work
getAssetFileAbsolutePath = async () => {
const dest =
`${RNFS.TemporaryDirectoryPath}${Math.random().toString(36)
.substring(
.7)}.png`;
const img = './images/page1.png';
try {
await RNFS.moveFile(img, dest);
console.log("dobro", dest)
} catch(err) {
console.log("greska", err)
}
}
I get error “page1.png” couldn’t be moved to “tmp” because either the former doesn’t exist, or the folder containing the latter doesn’t exist.
use rn-fetch blob with react native share
first find path of the image and convert it to base64.
then share image use react native share package
ShareFile(file) {
let imagePath = null;
RNFetchBlob.config({
fileCache: true
})
.fetch("GET", file)
// the image is now dowloaded to device's storage
.then(resp => {
// the image path you can use it directly with Image component
imagePath = resp.path();
return resp.readFile("base64");
})
.then(async base64Data => {
var base64Data = `data:image/png;base64,` + base64Data;
// here's base64 encoded image
await Share.open({ url: base64Data });
// remove the file from storage
return fs.unlink(imagePath);
});
}
I have a page that includes a download button using jsPDF. On desktop machines it downloads the page as it should. However, pdf.save() does not work on my tablet or phone.
I tried to add a special case for mobile devices to open the PDF in a new window, since mobile devices don't download things the same as desktops, with the idea being that once the PDF is open in a new window the user can choose to save it manually.
var pdf = new jsPDF('p', 'pt', 'letter');
var specialElementHandlers = {
'#editor': function (element, renderer) {
return true;
}
};
html2canvas($("#pdf-area"), {
onrendered: function (canvas) {
$("#pdf-canvas").append(canvas);
$("#pdf-canvas canvas").css("padding", "20px");
}
});
var options = {
pagesplit: true
};
function download(doctitle) {
pdf.addHTML($("#pdf-area")[0], options, function () {
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
pdf.output('dataurlnewwindow');
} else {
pdf.save(doctitle);
}
});
}
But the download function still does nothing on my tablet/phone. I tested it with this to make sure the pdf.output() function was working:
pdf.addHTML($("#pdf-area")[0], options, function () {
pdf.output('dataurlnewwindow');
});
and it does still work on desktop, but does nothing on mobile.
jsPDF won't download files on mobile apps by this pdf.save(). I have tried and searched for this issue but could not find a complete solution in one place. I am using the file and file-opener plugin. I have developed the solution in Ionic React. Install below modules.
npm i jspdf
npm install cordova-plugin-file
npm install #ionic-native/file
npm install cordova-plugin-file-opener2
npm install #ionic-native/file-opener
ionic cap sync
Go to your file and add these import statements.
import { jsPDF } from "jspdf";
import 'jspdf-autotable';
import { FileOpener } from '#ionic-native/file-opener;
import { File } from '#ionic-native/file';
import { isPlatform } from "#ionic/react";
Check the pdfDownload function
const pdfDownload = async () => {
var doc = new jsPDF();
doc.setFontSize(40);
doc.text("Example jsPDF", 35, 25)
let pdfOutput = doc.output();
if (isPlatform("android")) {
// for Android device
const directory = File.externalRootDirectory + 'Download/';
const fileName = `invoice-${new Date().getTime()}.pdf`
File.writeFile(directory, fileName, pdfOutput, true).then(succ => {
FileOpener.showOpenWithDialog(directory + fileName, 'application/pdf')
.then(() => console.log('File opened'))
.catch(error => console.log('Error opening file', error));
},
err => {
console.log(" writing File error : ", err)
})
} else if (isPlatform("ios")) {
// for iOS device
console.log('ios device')
const directory = File.tempDirectory;
const fileName = `invoice-${new Date().getTime()}.pdf`
File.writeFile(directory, fileName, pdfOutput, true).then(success => {
FileOpener.showOpenWithDialog(directory + fileName, 'application/pdf')
.then(() => console.log('File opened'))
.catch(e => console.log('Error opening file', e));
},
err => {
console.log(" writing File error : ", err)
})
} else {
// for desktop
doc.save("invoice.pdf");
}
}
I had similar issue.
jsPDF won't download file on phones/ tablets / ipads using "pdf.save()".
Do it through File plugin if you are using cordova/phonegap, this will save pdf file in downloads folder (Android) - for the ios you can access pdf file through a path (which is saved somewhere in temp directory) and can send or share.
Hope this helps you.
Here is the solution of download on mobile with jspdf
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
{
var blob = pdf.output();
window.open(URL.createObjectURL(blob));
}
else
{
pdf.save('filename.pdf');
}
Here is the example if you're using the Cordova platform for your development:
https://github.com/saharcasm/Cordova-jsPDF-Email
The workaround of the pdf not being downloaded in the devices is to use cordova-plugin-file.
Use the output method on the doc that will give you the raw pdf which needs to be written & saved in a file.
For example,
var doc = new JsPDF();
//... some work with the object
var pdfOutput = doc.output("blob"); //returns the raw object of the pdf file
The pdfOutput is then written on an actual file by using the file plugin.
The easiest way which works on both Desktop and Mobile is to use:
window.open(doc.output("bloburl"), "_blank");
I am developing a app where i need to upload an image to the server. Based on the image i get a response which i need to render?.
Can you please help me how to upload an image using react-native?.
There is file uploading built into React Native.
Example from React Native code:
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!');
var xhr = new XMLHttpRequest();
xhr.open('POST', serverURL);
xhr.send(body);
My solution is using fetch API and FormData.
Tested on Android.
const file = {
uri, // e.g. 'file:///path/to/file/image123.jpg'
name, // e.g. 'image123.jpg',
type // e.g. 'image/jpg'
}
const body = new FormData()
body.append('file', file)
fetch(url, {
method: 'POST',
body
})
I wrote something like that. Check out https://github.com/kamilkp/react-native-file-transfer
I have been struggling to upload images recently on react-native. I didn't seem to get the images uploaded. This is actually because i was using the react-native-debugger and network inspect on while sending the requests. Immediately i switch off network inspect, the request were successful and the files uploaded.
I am using the example from this answer above it works for me.
This article on github about the limitations of network inspect feature may clear things for you.
Just to build on the answer by Dev1, this is a good way to upload files from react native if you also want to show upload progress. It's pure JS, so this would actually work on any Javascript file.
(Note that in step #4 you have to replace the variables inside the strings with the type and file endings. That said, you could just take those fields out.)
Here's a gist I made on Github: https://gist.github.com/nandorojo/c641c176a053a9ab43462c6da1553a1b
1. for uploading one file:
// 1. initialize request
const xhr = new XMLHttpRequest();
// 2. open request
xhr.open('POST', uploadUrl);
// 3. set up callback for request
xhr.onload = () => {
const response = JSON.parse(xhr.response);
console.log(response);
// ... do something with the successful response
};
// 4. catch for request error
xhr.onerror = e => {
console.log(e, 'upload failed');
};
// 4. catch for request timeout
xhr.ontimeout = e => {
console.log(e, 'cloudinary timeout');
};
// 4. create formData to upload
const formData = new FormData();
formData.append('file', {
uri: 'some-file-path', // this is the path to your file. see Expo ImagePicker or React Native ImagePicker
type: `${type}/${fileEnding}`, // example: image/jpg
name: `upload.${fileEnding}` // example: upload.jpg
});
// 6. upload the request
xhr.send(formData);
// 7. track upload progress
if (xhr.upload) {
// track the upload progress
xhr.upload.onprogress = ({ total, loaded }) => {
const uploadProgress = (loaded / total);
console.log(uploadProgress);
};
}
2. uploading multiple files
Assuming you have an array of files you want to upload, you'd just change #4 from the code above to look like this:
// 4. create formData to upload
const arrayOfFilesToUpload = [
// ...
];
const formData = new FormData();
arrayOfFilesToUpload.forEach(file => {
formData.append('file', {
uri: file.uri, // this is the path to your file. see Expo ImagePicker or React Native ImagePicker
type: `${type}/${fileEnding}`, // example: image/jpg
name: `upload.${fileEnding}` // example: upload.jpg
});
})
In my opinion, the best way to send the file to the server is to use react-native-fs package, so install the package
with the following command
npm install react-native-fs
then create a file called file.service.js and modify it as follow:
import { uploadFiles } from "react-native-fs";
export async function sendFileToServer(files) {
return uploadFiles({
toUrl: `http://xxx/YOUR_URL`,
files: files,
method: "POST",
headers: { Accept: "application/json" },
begin: () => {
// console.log('File Uploading Started...')
},
progress: ({ totalBytesSent, totalBytesExpectedToSend }) => {
// console.log({ totalBytesSent, totalBytesExpectedToSend })
},
})
.promise.then(({ body }) => {
// Response Here...
// const data = JSON.parse(body); => You can access to body here....
})
.catch(_ => {
// console.log('Error')
})
}
NOTE: do not forget to change the URL.
NOTE: You can use this service to send any file to the server.
then call that service like the following:
var files = [{ name: "xx", filename:"xx", filepath: "xx", filetype: "xx" }];
await sendFileToServer(files)
NOTE: each object must have name,filename,filepath,filetype
A couple of potential alternatives are available. Firstly, you could use the XHR polyfill:
http://facebook.github.io/react-native/docs/network.html
Secondly, just ask the question: how would I upload a file in Obj-C? Answer that and then you could just implement a native module to call it from JavaScript.
There's some further discussion on all of this on this Github issue.
Tom's answer didn't work for me. So I implemented a native FilePickerModule which helps me choose the file and then use the remobile's react-native-file-transfer package to upload it. FilePickerModule returns the path of the selected file (FileURL) which is used by react-native-file-transfer to upload it.
Here's the code:
var FileTransfer = require('#remobile/react-native-file-transfer');
var FilePickerModule = NativeModules.FilePickerModule;
var that = this;
var fileTransfer = new FileTransfer();
FilePickerModule.chooseFile()
.then(function(fileURL){
var options = {};
options.fileKey = 'file';
options.fileName = fileURL.substr(fileURL.lastIndexOf('/')+1);
options.mimeType = 'text/plain';
var headers = {
'X-XSRF-TOKEN':that.state.token
};
options.headers = headers;
var url = "Set the URL here" ;
fileTransfer.upload(fileURL, encodeURI(url),(result)=>
{
console.log(result);
}, (error)=>{
console.log(error);
}, options);
})
Upload Files : using expo-image-picker npm module. Here we can upload any files or images etc. The files in a device can be accessed using the launchImageLibrary method. Then access the media on that device.
import * as ImagePicker from "expo-image-picker";
const loadFile = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
aspect: [4, 3],
});
return <Button title="Pick an image from camera roll" onPress={loadFile} />
}
The above code used to access the files on a device.
Also, use the camera to capture the image/video to upload by using
launchCameraAsync with mediaTypeOptions to videos or photos.