How to upload Image on server using ReactNative - android

I am setting headers and body , Using fetch with Post to upload image on server.I am getting the response code 200 but it is not uploading image but rest of the Data is getting uploaded.
Here is the code of body:
export default function setRequestBody(imagePath){
let boundry = "----WebKitFormBoundaryIOASRrUAgzuadr8l";
let body = new FormData();
body.append("--"+boundry+"\r\n");
body.append("Content-Disposition: form-data; name=imageCaption\r\n\r\n");
body.append("Caption"+"\r\n");
body.append("--"+boundry+"\r\n");
body.append("Content-Disposition: form-data; name=imageFormKey; filename =iimageName.pngg \r\n");
body.append("Content-Type: image/png \r\n\r\n");
body.append({uri : imagePath});
// appened image Data Here
body.append("\r\n");
body.append("--"+boundry+"--\r\n");
return body
}
Please help.What mistake I am making. :(

I've found the solution:
let body = new FormData();
body.append('photo', {uri: imagePath,name: 'photo.png',filename :'imageName.png',type: 'image/png'});
body.append('Content-Type', 'image/png');
fetch(Url,{ method: 'POST',headers:{
"Content-Type": "multipart/form-data",
"otherHeader": "foo",
} , body :body} )
.then((res) => checkStatus(res))
.then((res) => res.json())
.then((res) => { console.log("response" +JSON.stringify(res)); })
.catch((e) => console.log(e))
.done()
** filename is optional...

The problem is body.append({uri : imagePath}); because react native JSC does not support File and Blob, so you have to use libraries.
react-native-fetch-blob has very good support for this, example from its README.md
RNFetchBlob.fetch('POST', 'http://www.example.com/upload-form', {
Authorization : "Bearer access-token",
otherHeader : "foo",
'Content-Type' : 'multipart/form-data',
}, [
// element with property `filename` will be transformed into `file` in form data
{ name : 'avatar', filename : 'avatar.png', data: binaryDataInBase64},
// custom content type
{ name : 'avatar-png', filename : 'avatar-png.png', type:'image/png', data: binaryDataInBase64},
// part file from storage
{ name : 'avatar-foo', filename : 'avatar-foo.png', type:'image/foo', data: RNFetchBlob.wrap(path_to_a_file)},
// elements without property `filename` will be sent as plain text
{ name : 'name', data : 'user'},
{ name : 'info', data : JSON.stringify({
mail : 'example#example.com',
tel : '12345678'
})},
]).then((resp) => {
// ...
}).catch((err) => {
// ...
})

I've found the solution to Upload the Image on server in React Native:
const formdata = new FormData();
formdata.append('image[]', {
name: 'test.' + imageurl?.type?.substr(6),
type: imageurl?.type,
uri:
Platform.OS !== 'android'
? 'file://' + imageurl?.uri
: imageurl?.uri,
});
const res = await axios.post(url, formdata, {
headers: {
Accept: '*/*',
'Content-type': 'multipart/form-data',
},
});

//First Install and import Image-piker
//install
npm i react-native-image-picker
//import
import * as ImagePicker from 'expo-image-picker';
//then
const [image, setImage] = React.useState(null);
const [Type,setType]=React.useState('')
//Get the image
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result);
if (!result.cancelled) {
// extract the filetype
setType(result.uri.substring(result.uri.lastIndexOf(".") + 1));
setImage(result.uri);
}
};
//show image return
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button title="Ecolher Foto" onPress={pickImage} />
{image && <Image source={{ uri: image }} style={{ width: 150, height: 150 }} />}
</View>
//UpLoad Image
var validatinoApi ='https://seusite.com/OOP/';
var headers={
'Accept':'application/json',
"Content-Type": "multipart/form-data",
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Origin':'*',
'crossDomain': 'true',
'Host': 'https://seusite.com/OOP/',
'Origin': 'https://origem.com',
};
/*'crossDomain': 'true',*/
var Data={
image:image,
namefoto: `photo.${namefoto}`,
type: `image/${Type}`
};
fetch(validatinoApi,
{
method:'POST',
headers:headers,
body:JSON.stringify(Data)
}).then((response)=>response.json())
.then((response)=>{
if(response.statusCode==200){
//Do something
}

Related

I'm getting 'undefined is not an object (near '...}).fs.writeFile(' when trying to download base64 image png in react native React Native

Here is my code:
const saveImg = async (base64Img: string, success: Function, fail:Function) => {
const isAndroid = Platform.OS === "android"
const isIos = Platform.OS === 'ios'
const dirs = isIos? RNFS.LibraryDirectoryPath : RNFS.ExternalDirectoryPath;
const certificateTitle = 'certificate-'+((Math.random() * 10000000) | 0)
const downloadDest = `${dirs}/${certificateTitle}.png`;
const imageDatas = base64Img.split('data:image/png;base64,');
const imageData = imageDatas[1];
try{
await RNFetchBlob.config({
addAndroidDownloads:{
notification:true,
description:'certificate',
mime:'image/png',
title:certificateTitle +'.png',
path:downloadDest
}
}).fs.writeFile(downloadDest, imageData, 'base64')
if (isAndroid) {
} else {
RNFetchBlob.ios.previewDocument(downloadDest);
}
success()
}catch(error:any){
console.log(error)
fail()
}
}
I get this error:
undefined is not an object (near '...}).fs.writeFile(downloadD...')
at node_modules/react-native-webview/lib/WebView.android.js:207:16 in _this.onMessage
When I hit the download button and this runs I get the mentioned Error.
I use to get the download done with the below code modification, but I really need to show the download feedback from both android and IOS.
This works (but without notification)
await RNFetchBlob.fs.writeFile(downloadDest, imageData, 'base64')
I am using expo
I discovered that the react-fetch-blob does not work with expo, to solve it, I used the following libraries:
expo-file-system, expo-media-library, expo-image-picker,expo-notifications
This was the code to convert, download and show the notification of the image in the "expo way":
import * as FileSystem from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
import * as ImagePicker from 'expo-image-picker';
import * as Notifications from 'expo-notifications';
const saveImg = async (base64Img: string, success: Function, fail:Function) => {
const imageDatas = base64Img.split('data:image/png;base64,');
const imageData = imageDatas[1];
try {
const certificateName = 'certificate-'+((Math.random() * 10000000) | 0) + ".png"
const certificatePathInFileSystem = FileSystem.documentDirectory +certificateName ;
await FileSystem.writeAsStringAsync(certificatePathInFileSystem, imageData, {
encoding: FileSystem.EncodingType.Base64,
});
await MediaLibrary.saveToLibraryAsync(certificatePathInFileSystem);
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: true,
}),
});
await Notifications.scheduleNotificationAsync({
content: {
title: certificateName +' saved !',
body: "Click to show the certificate",
},
trigger: null,
});
setCertificatePath(certificatePathInFileSystem)
success()
} catch (e) {
console.error(e);
fail()
}
}
In order to open the images gallery on click I used this code:
useEffect(()=>{
if(certificatePath){
Notifications.addNotificationResponseReceivedListener( async (event )=> {
await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
})
})
}
},[certificatePath])
Try to call fetch after create RNFetchBlob.config
If you just wanna display an Image and not store you can show image as fallows (https://reactnative.dev/docs/next/images#uri-data-images)
<Image
style={{
width: 51,
height: 51,
resizeMode: 'contain'
}}
source={{
uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg=='
}}
/>
Call fetch on config object:
try{
const fetchConfig = await RNFetchBlob.config({
addAndroidDownloads:{
notification:true,
description:'certificate',
mime:'image/png',
title:certificateTitle +'.png',
path:downloadDest
}
})
fetchConfig.fetch('your.domain.com').fs.writeFile(downloadDest, imageData, 'base64')
if (isAndroid) {
} else {
RNFetchBlob.ios.previewDocument(downloadDest);
}
success()
}catch(error:any){
console.log(error)
fail()
}

Upload a file from react native image picker to server

can someone tell me what i m doing wrong i keep getting error 400 bad request, i can't seem to figure out how to send the image i tried to send the path, the filename and the mime but it's not working this is my request:
const [image,setImage]=useState(null)
const[filename,setFileName]=useState(null)
const sendpic=async ()=>{
await ImagePicker.openCamera({
mediaType:'photo',
width: 300,
height: 400,
cropping: false,
}).then(image => {
setImage(image['path']);
const paths=image['path']
const filename=paths.substring(paths.lastIndexOf('/')+1);
setFileName(filename);
console.log(filename)
console.log(image)
const data=new FormData();
data.append('image',filename)
data.append('title','3aslemajiti')
const headers={
Accept:'application/json',
'Content-Type':'multipart/form-data',
}
try{
const response= axios.post('http://192.168.1.19:8000/Sends/',data,{headers:headers})
alert('yess!!!!!');
}
catch (error) {
// handle error
alert(error.message);
}
});
};
and this is my model:
from django.db import models
# Create your models here.
class Send(models.Model):
title = models.CharField(max_length=255)
image=models.ImageField(default ='null')
def __str__(self):
return self.title
how do i write the request so it is accepted by the server?
data.append('image', {
uri: filename,
name: 'test.jpg',
type: 'image/jpeg'
});
Image upload format should be this and please check file url should be correct.
"uri": "file:///Users/user/Library/Developer/CoreSimulator/Devices/33198C8D-55D3-4555-B9B5-DC1A61761AAF/data/Containers/Data/Application/B5067299-1CD2-4000-8935-59B59ED447F6/tmp/871EB6D5-2408-4A10-8DE7-EE52B1855ECD.jpg"
this is url for image. it should be like this.
const data = new FormData();
data.append("uploadFile", {
name: filename,
type: filetype,
uri:
Platform.OS === "android"
? fileuri
: fileuri.replace("file://", "")
});
var url = uploadDoc
axios.post(url, data, {headers: {
"Content-Type": "multipart/form-data",
Accept: "application/json",
Authorization: authToken
}})
.then((res) => {
})
.catch((err) => {
})

Image upload with axios react native android

I am trying to upload image to an API the iOS version is working good but there is problem in android, My code is bellow.
const uploadUri =
Platform.OS === 'ios'
? uploadImageFile.replace('file:', '')
: uploadImageFile;
// console.log(uploadUri);
const data = new FormData();
data.append('file', {
uri: uploadUri,
name: 'file',
type: 'image/jpg',
});
Axios.post(`${API.BASE_URL}/user/image`, data, {
headers: {
Authorization: token,
'Content-Type': 'multipart/form-data',
},
})
.then((res) => {
setActivity(false);
setIsImageEdit(false);
console.log('success');
})
.catch((error) => {
setActivity(false);
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log('Error', error.message);
}
setIsImageEdit(false);
});
The error response I get is
{"DONE": 4, "HEADERS_RECEIVED": 2, "LOADING": 3, "OPENED": 1, "UNSENT": 0, "_aborted": false, "_cachedResponse": undefined, "_hasError": true, "_headers": {"accept": "application/json, text/plain, */*", "authorization": "7aeb23f62bd748c39c9e8652eb1056e2"}, "_incrementalEvents": false, "_lowerCaseResponseHeaders": {}, "_method": "POST", "_perfKey": "network_XMLHttpRequest_https://capi-test.beebl.io/user/image", "_requestId": null, "_response": "Could not retrieve file for uri /storage/emulated/0/Pictures/images/image-448777a5-1734-41f4-857e-a99d5239c279.jpg", "_responseType": "", "_sent": true, "_subscriptions": [], "_timedOut": false, "_trackingName": "unknown", "_url": "https://capi-test.beebl.io/user/image", "readyState": 4, "responseHeaders": undefined, "status": 0, "timeout": 0, "upload": {}, "withCredentials": true}
"_response": "Could not retrieve file for uri /storage/emulated/0/Pictures/images/image-448777a5-1734-41f4-857e-a99d5239c279.jpg"
I fixed it by adding
android:requestLegacyExternalStorage="true"
in AndroidManifest.xml

React-Native multipart photo upload not working in android

I'm trying to send/upload image file to my back-end serve using fetch multipart upload in react-native, but fetch multipart form data upload is not working for android, however I tried different examples.
Image upload multipart form data API is based on php and its working for iOS react-native app.
I am using react-native-photo-upload library for taking image.
storePicture(PicturePath:string) {
console.warn(PicturePath);
if (PicturePath) {
const apiUrl = `${Constants.APIHOST}updateprofileimage.php`;
// Create the form data object
var data = new FormData();
data.append('profileimage', { uri:PicturePath, name: 'profileimage.jpg', type: 'image/jpg/jpeg' });
data.append('accesstoken', this.state.user.sAccessToken);
data.append('react-native', 1);
// Create the config object for the POST // You typically have an OAuth2 token that you use for authentication
const config = { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'multipart/form-data;' }, body: data };
fetch(apiUrl, config)
.then(responseData => { // Log the response form the server
// Here we get what we sent to Postman back
console.warn(`response:${responseData}`);
})
.catch(err => {
console.warn(err);
});
}}
Here is the example how I am calling storePicture() function.
<PhotoUpload onResizedImageUri={
avatar => {
if (avatar) {
this.storePicture(avatar.path);
}
}}
>
<Image source={{uri: this.state.user.sProfileImageUrl}} style={{resizeMode:"cover", marginTop:8.0, backgroundColor:'transparent', height:120.0, width:120, borderRadius:60.0, borderWidth:0.0, borderColor:'transparent'}}/>
</PhotoUpload>
uploadProfileImage = async (image:var) => {
this.setState({
loading: true
});
var RNFS = require('react-native-fs');
const path = Style.IS_IOS ? image.uri : image.path;
var fileName = path.split('/').pop();
var fileType = fileName.split('.').pop();
var filePath = Style.IS_IOS ? path : 'file://' + path;
const apiURL = `${Constants.APIHOST}updateprofileimage.php`;
const formData = new FormData();
formData.append('accesstoken', this.state.user.sAccessToken);
formData.append('reactnative', 1);
formData.append('profileimage', {
uri:filePath,
name: fileName,
type: `image/${fileType}`,
});
try {
const response = await fetch(apiURL, {
body: formData,
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
},
})
const json = await response.json()
this.handleUploadImageResponse(json);
} catch (err) {
this.setState({
loading: false
},console.log('catch Error: '+ err));
}
}
I am answering my own question as I haven't found any valid answer for the sake of other users, who are facing same issue.
Please let me know if I can improve my answer/post or in case any help is needed from me.
Image Upload to an API by Multipart FormData
uploadPicture = () => {
console.log(
"Image Upload urI = " + JSON.stringify(this.state.imageSourceUri.uri)
);
this.setState({ loading: true });
const form = new FormData();
form.append("fileToUpload", {
uri: this.state.imageSourceUri.uri,
type: "image/jpg",
name: "12334"
});
fetch("http://119.82.97.221/HPBSProjectApi2/api/HPBS/PostFormData", {
method: "post",
body: form
})
.then(response => response.json())
.then(response => {
console.log("response = " + response);
this.setState({
loading: false
});
});
};
the problem is the type field in the FormData, use mime to resolve it. Images must be image/jpeg.
const formData = new FormData();
formData.append("image",{..., name, uri, type: mime.getType(uri)}));

Pdf does not appears on Android

I'm using the library react-native-pdf to show it.
Its frame is okay because I've set the background in blue.
I'm doing a RNFetchBlob.fs.exists(path) just before and the value is true but nothing appears on pdf viewer
Any idea ? I have no log or whatever which tell me there is a problem.
<Pdf source={{uri : filePath}}
style={{backgroundColor: 'grey', flex : 1}}/>
Here is how I show the pdf.
const request = RNFetchBlob
.config(this.getConfig(title, ext))
.fetch('GET', uri, header);
this.setState(
() => {
return {request: request}
},
() => {
this.state.request.then((res) => {
if (Platform.OS === 'android') {
const path = res.path()
const infos = res.info()
console.log(infos)
if (path !== undefined){
this.setState(() => {
return {
filePath : path
}
})
The file path is returned by the res.path()
addAndroidDownloads: {
useDownloadManager: true,
notification: false,
path: filePath,
description: `${title}`,
mediaScannable: true,
}
The variable config is made like this.

Categories

Resources