I am trying to upload files to server in react-native application with axios as http handler.
My code stands as:
let promises = [];
const body = new FormData();
console.log(body);
body.append('device_name', this.state.deviceInfo.DeviceName);
body.append('device_id', this.state.deviceInfo.DeviceID);
body.append('device_ip', this.state.deviceInfo.DeviceIP);
body.append('device_os', this.state.deviceInfo.DeviceOS);
body.append('upload_type', 'user');
body.append('user_name', user.Email);
body.append('file1', {
uri: this.state.newImageUrl.uri,
name: 'test.jpg',
type: 'image/jpg',
});
promises.push(
apiUploadDocs(body)
.then(res => {
profileImageName = res[0].NewFileName;
})
.catch(err => {
console.log('this error', err);
}),
);
My apiUploadDocs is as :
export const apiUploadDocs = body => {
return new Promise((resolve, reject) => {
axios
.post(ApiRoutes.uploadDocs, body,{headers:{'content-Type': `multipart/form-data`}})
.then(res => {
console.log('upload success');
console.log(res);
})
.catch(err => {
console.log('upload error', err);
if (err.response) {
}
reject(Constant.network.networkError);
});
});
};
Every assigned variable has correct values upon logging and the api is working good when I try to upload from Postman.
But this snippet here results in an error which is undefined when logged.
I have tried trimming the 'file://' from the uri, as suggested by some answers here in stackoverflow.
I cant figure it out. Can you help me finding whats wrong here??
PS: The body when logged is:
{
"_parts":[
[
"device_name",
"sdk_gphone_x86"
],
[
"device_id",
"xxxxxxxxxxxxx"
],
[
"device_ip",
"10.0.2.xx"
],
[
"device_os",
"goldfish_x86"
],
[
"upload_type",
"user"
],
[
"user_name",
"xxxxx#gmail.com"
],
[
"file1",
[
"Object"
]
]
]
}
if it is of any reference.
I've found a link to uploading image in react-native.
https://aboutreact.com/file-uploading-in-react-native/
This might be of some help to you.
let uploadImage = async () => {
//Check if any file is selected or not
if (singleFile != null) {
//If file selected then create FormData
const fileToUpload = singleFile;
const data = new FormData();
data.append('name', 'Image Upload');
data.append('file_attachment', fileToUpload);
let res = await fetch(
'http://localhost//webservice/user/uploadImage',
{
method: 'post',
body: data,
headers: {
'Content-Type': 'multipart/form-data; ',
},
}
);
let responseJson = await res.json();
if (responseJson.status == 1) {
alert('Upload Successful');
}
} else {
//if no file selected the show alert
alert('Please Select File first');
}
};
Related
I am trying to upload an image from my react native app.
If I use my local node server and run this code:
var fs = require("fs");
var options = {
method: "POST",
url: "my_URL",
headers: {},
formData: {
file: {
value: fs.createReadStream("../../assets/image.png"),
options: {
filename: "image.jpg",
contentType: null
}
}
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
I have a succesful upload.
However, with the URI from that we get through the the app, it does not work:
Here is my code on React Native Expo:
const body = new FormData();
body.append("file", 'file:///path/to/file/image123.jpg');
fetch(url, {
method: "POST",
body,
headers: {
"content-type": "multipart/form-data"
}
})
.then(response => {
console.log(response, "RESPONSE");
})
.then(result => {
console.log(result, "RESULT");
})
.catch(error => {
console.log(error, "ERROR");
});
I am unable to get it to work. I think it has something to do with the file path from the device.
Any help will be appreciated.
try to create FormData using this function
const createFormData = (uri) => {
const fileName = uri.split('/').pop();
const fileType = fileName.split('.').pop();
const formData = new FormData();
formData.append('file', {
uri,
name: fileName,
type: `image/${fileType}`
});
return formData;
}
if it doesn't work check permissions
can anyone tell me what wrong with this code im trying to upload image using react-native-image-picker in react native.but it says localUri.split is not defined and sending data shows in inspect element as {_parts:[[]]} and why this _parts coming every post method ...please help me to figure out this..
const takeAndUploadPhotoAsync = async () => {
const token = await AsyncStorage.getItem("userToken");
let result = await launchImageLibrary();
if (result.cancelled) {
return;
}
let localUri = result.uri;
let filename = localUri.split('/').pop().split('#')[0].split('?')[0]
let match = /\.(\w+)$/.exec(filename);
let type = match ? `image/${match[1]}` : `image`;
const url = `/auth/upload-prescription`;
let formData = new FormData();
formData.append("file", { uri: localUri, name: filename, type });
setLoading(true);
const response = await api
.post(url, formData, {
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data',
},
})
.then((res) => {
showMessage({
message: "Your Prescription is Uploaded Successfully",
textStyle: {textAlign:'center'},
type: "success",
backgroundColor: "#202877",
});
})
.catch((error) => {
console.log(error.response);
});
dispatch({
type: "TAKE_AND_UPLOAD_PHOTO_ASYNC",
payload: response,
});
setLoading(false);
};
I'm receieving a blob from api and i want to save it as a pdf document to file system.But on saving I'm getting a file with size 0B in my mobile
Code
export const getParkingReciept = (bookindId) => {
return async function (dispatch, getState) {
try {
const TOKEN = getState().Auth.token;
const formdata = new FormData();
formdata.append("booking_id", bookindId);
RNFetchBlob.fetch(
'POST',
`${BASE_URL}parking-space/booking/receipt`,
{
'Accept': 'application/json',
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'multipart/form-data'
},[
{ name : 'booking_id', data: bookindId.toString()}
]
)
.then(
response => {
console.log("response is ",response);
response.blob().then(res=>console.log(checkPermission(res,response.taskId)));
console.log("pdf base64 is ", response.base64());
}
).catch((error) => {
// error handling
console.log("Error", error)
}
);
}catch (e) {
if (e.response) {
console.log("error response is ", e.response);
} else if (e.request) {
console.log(e.request);
} else {
console.log('Error', e);
}
console.log(e.config);
}
}
const checkPermission=async (file,name) => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
{
title: "Cool Photo App Camera Permission",
message:
"Cool Photo App needs access to your camera " +
"so you can take awesome pictures.",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can write to external storage");
var path = RNFS.DownloadDirectoryPath + '/'+name+".pdf";
console.log("pdf being written is ",file);
RNFS.writeFile(path, file, 'utf8')
.then((success) => {
console.log('FILE WRITTEN!');
RNFetchBlob.fs.scanFile([ { path : path, mime : "application/pdf" } ])
// .then(() => {
// console.log("scan file success")
// })
// .catch((err) => {
// console.log("scan file error")
// })
})
.catch((err) => {
console.log(err.message);
});
} else {
console.log("permission denied");
}
} catch (err) {
console.warn(err);
}
};
reponse I get from fetch is
on calling blob() function of response what I get is
There is type Application/pdf there ,but in base 64 string does not start with JVBERi it starts with some SFRUU,Is that a valid pdf file?. What am I missing ? what am I doing wrong here?
This answer solves your problem , gives you detailed explanation about how to download files from a network request using rn fetch blob
https://stackoverflow.com/a/56890611/7324484
Once you downloaded the file or you can open the pdf directly using
https://www.npmjs.com/package/react-native-pdf
I have below code
async send(user, data) {
const postData = {
'data': 'john',
'secret': 'secret'
};
const dataJson = JSON.stringify(postData);
const options = {
hostname: 'example.com',
path: '/send',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': dataJson.length
}
};
const req = https.request(options, (res) => {
let data = '';
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
req.write(dataJson);
req.end();
//---------------
let postResult = // HERE I WANT TO GET WHAT HTTP POST REQUESTED (e.g dataJson.body?)
//---------------
let result;
try {
result = await this.users.collection('users').updateOne(
{
_id: user
},
{
$set: {
// I WANT TO USE THAT HERE
data1 : postResult,
data2 : data2
}
},
{ maxTimeMS: consts.DB_MAX_TIME_USERS }
);
} catch (err) {
log.error('DB', 'UPDATEFAIL id=%s error=%s', user, err.message);
err.message = 'Database Error, failed to update user';
err.code = 'InternalDatabaseError';
throw err;
}
return { success: true };
}
How to get those data to outside variable?
I almost crazy about this, been searching on google and not found anything
I am using express and native-http to make http request, are there any native-curl maybe?
thank you very much for all the help
Your current code is using callback to retrieve result, so you can initiate data variable to outside callback function
let data = '';
const req = https.request(options, (res) => {
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
})
And also there are other easier way to make http request with nodejs. you can check axios that support Promise and async/await.
you can use syntax like this with axios
const response = await axios.get('/user?ID=12345');
way more easier.
I created two custom endpoints with Loopback.
Account.deleteAllHearingTests = function (req, callback) {
console.log('here comes the req to delete all hearing tests', req);
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('cannot find user');
}
return app.models.HearingTest.updateAll({ accountId: account.id }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
})
}
Account.remoteMethod(
'deleteAllHearingTests', {
http: {
path: '/clearHearingTests',
verb: 'post'
},
accepts: [
{ arg: 'req', type: 'object', http: { source: 'req' } }
],
returns: {}
}
);
the second one looks like this.
Account.deleteSingleHearingTest = function (req, callback) {
// console.log('accounts.js: deleteSingleHearingTest: are we being reached????', req)
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('Cannot find user');
}
console.log('account.js: deleteSingleHearingTest: req.body.hearingTestId N: ', req.body.hearingTestId);
return app.models.HearingTest.updateAll({ accountId: account.id, id: req.body.hearingTestId }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
});
}
Account.remoteMethod(
'deleteSingleHearingTest', {
http: {
path: '/deleteSingleHearingTest',
verb: 'post'
},
accepts: [
{ arg: 'req', type: 'object', description: 'removes a single hearing test', http: { source: 'req' } }
],
description: 'this is the end point for a single delete',
returns: {}
}
);
};
The first custom method returns a 401 status response when I make the initial fetch. The second returns a 200.
Inside my actions file the first method is called with something that looks like this:
export function deleteAllHearingTests() {
return (dispatch, getState) => {
let state = getState();
if (!state.user || !state.user.accessToken || !state.user.accessToken.id || !state.user.accessToken.userId) {
console.debug('deleteAllHearingTests', state.user);
// TODO: ERROR
return;
}
fetch(SERVERCONFIG.BASEURL + '/api/Accounts/clearHearingTests?access_token=' + state.user.accessToken.id, {
method: 'POST',
headers: SERVERCONFIG.HEADERS
})
.then(response => {
console.log('here is your response', response);
if (response.status !== 200) {
throw new Error('Something is wrong');
}
return response.json()
})
the second method is called with
export const deleteSingleHearingTest = (hearingTestNumber) => {
return (dispatch, getState) => {
let state = getState();
if (!state.user || !state.user.accessToken || !state.user.accessToken.id || !state.user.accessToken.userId) {
console.debug('writeTestResult', state.user);
// TODO: ERROR
return;
}
console.log('single delete ', SERVERCONFIG.BASEURL + '/api/Accounts/deleteSingleHearingTest?access_token=' + state.user.accessToken.id)
fetch(SERVERCONFIG.BASEURL + '/api/Accounts/deleteSingleHearingTest?access_token=' + state.user.accessToken.id, {
method: 'POST',
headers: SERVERCONFIG.HEADERS,
body: JSON.stringify({ "hearingTestId": hearingTestNumber })
})
.then(response => {
console.log('getting response from initial fetch inside deleteSingleReqport', response);
They are nearly identical, however, one works..the other fails. What are some possible causes for the 401?
Did you try to call those methods with external tool like a postman, so you would exactly know if you don't miss access_token or something else? Also, when you compare code from one function and another, you can see that you are colling the updateAll with different arguments. It's hard to say without original code, but maybe the issue is there? Compare below:
return app.models.HearingTest.updateAll(
{ accountId: account.id },
{ isDeleted: new Date() });
return app.models.HearingTest.updateAll(
{ accountId: account.id, id: req.body.hearingTestId },
{ isDeleted: new Date() });
Additionally, in fetch method they are also diffferences, you are missing in one case the below:
body: JSON.stringify({ "hearingTestId": hearingTestNumber })
What you could also do to debug and to provide more data is to run server in debug mode by calling:
export DEBUG=*; npm start