I have a Angular application which makes post request like the following:
async syncDataWithMaster(): Promise<AxiosResponse<any> | void> {
....
const jsonData = {
lastSyncTimeStamp,
deviceID,
userUUID,
lData,
aData,
aiData,
fData,
oData,
caData,
};
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded/json/gzip';
axios.defaults.headers.post.Authorization = token;
const url = this.endpoint + 'syncData.php';
return axios.post(url, jsonData, {
onUploadProgress: progressEvent => {console.log('uploading')},
onDownloadProgress: progressEvent => {console.log('downloading')}
}).then((response) => {
if (response.data.status == 'success') {
return response;
} else {
throw new Error('Could not authenticate user');
}
});
} catch (e) {
}
return;
}
Usually this is fine for most of my user however some users have data up to 15-30mb. I am wondering if it possible to compress the data and send it to my PHP webserver which can then be decoded so that the upload is quicker?
Maybe consider using a compression library (depending on the content of the body). It looks like fflate can do this.
Related
I am new to react native. I am trying to upload my digital signature image which is stored in internal storage.
path is like this = '/storage/emulated/0/DCIM/1616657741752.png'.
but image not uploading then think that the problem is with this path - '/storage/emulated/0'.
because there no folder called DCIM in '/storage/emulated/0' this path.
so I remove this - '/storage/emulated/0' by using below code
this.setState({base64: paths.split('/storage/emulated/0').pop()})
But still same problem my image not uploading to server. over all my image is visible in my phone internal storage in DCIM folder. I do not know what to do now.
here is my code
base64:null,
_onSaveEvent = (result) => {
this.checkAndroidPermission(result)
}
checkAndroidPermission = async (result) => {
if (Platform.OS === 'ios') {
save(result);
} else {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
// Once user grant the permission start downloading
this.save(result);
} else {
if (Platform.OS === 'android') {
ToastAndroid.show('Storage Permission denied.', ToastAndroid.SHORT);
} else {
AlertIOS.alert('Storage Permission denied.');
}
}
} catch (err) {
// To handle permission related exception
console.warn('tryerr', err);
}
}
};
save = async (result) => {
const paths = `${
RNFetchBlob.fs.dirs.DCIMDir
}/${new Date().getTime()}.png`; // where u need to put that
try {
RNFetchBlob.fs
.writeFile(paths, result.encoded, 'base64')//data.base64 is your photo with convert base64
.then((value) => {
RNFetchBlob.fs
.scanFile([{path: paths}]) //after save to notify gallry for that
.then(() => {
this.setState({base64: paths.split('/storage/emulated/0').pop()})
console.log('scan file success');
console.log("this is fuckiiing file"+ this.state.base64)
})
.catch((err) => {
console.log('scan file error');
});
})
.catch((e) => console.log(e.message));
} catch (error) {
console.log('fileerror', error.message);
}
}
formData.append('digital_signature',this.state.base64);
console.log(JSON.stringify(formData))
fetch('https://abc.tech/Android_API_CI/upload_multipart_data',
{
method: 'post',
body : formData,
headers: {
'Content-Type': 'multipart/form-data;',
},
<SignatureCapture
style={styles.signature}
ref="sign"
onSaveEvent={this._onSaveEvent}
onDragEvent={this._onDragEvent}
saveImageFileInExtStorage={true}
showNativeButtons={false}
showTitleLabel={false}
viewMode={'portrait'}
/>
Here is your Ans and also put into the function may this helps
const file = {
uri:
Platform.OS == 'android'
? '/storage/emulated/0/DCIM/1616657741752.png' //path to your file
: 'file:///storage/emulated/0/DCIM/1616657741752.png',
name: 'sign.png', // which go on server on your file name
type: 'image/png', // e.g. 'image/jpg'
};
formData.append('digital_signature',file);
console.log(JSON.stringify(formData))
fetch('https://abc.tech/Android_API_CI/upload_multipart_data',
{
method: 'post',
body : formData,
headers: {
'Content-Type': 'multipart/form-data;',
},
Somewhere in my React application I used REST API to send request to the server. In my URL I want to use query (in the postIconsTransition method), but when I send a request to the server, server tells me could not found this URL (I build this error in my server). If I use this URL without any query the request in the postIconsTransition method works fine. postId and authContext.userId work fine, can anyone tell me what's wrong with my code?
In my component where I send request:
const likeHandler = async () => {
setLike(prevState => !prevState);
if (!like) {
try {
await postIconsTransition(props.postId, "inc");
} catch (error) {}
} else {
try {
await postIconsTransition(props.postId, "dec");
} catch (error) {}
}
};
In useHttp.js component:
const postIconsTransition = async (postId, addtionAddress) => {
return await transitionData(
`http://localhost:5000/post/${postId}/${authContext.userId}?t=${addtionAddress}`,
"POST",
null,
{ Authorization: `Bearer ${authContext.token}` }
);
};
transitionData method:
const transitionData = useCallback(
async (url, method = "GET", body = null, headers = {}) => {
setIsLoading(true);
const abortController = new AbortController();
activeHttpRequest.current.push(abortController);
try {
const response = await fetch(url, {
method,
body,
headers,
signal: abortController.signal
});
const responseData = await response.json();
activeHttpRequest.current = activeHttpRequest.current.filter(
reqCtrl => reqCtrl !== abortController
);
if (!response.ok) {
throw new Error(responseData.message);
}
setIsLoading(false);
return responseData;
} catch (error) {
modalContext.err(error);
setIsLoading(false);
throw error;
}
},
[modalContext.err]
);
In Express:
router.post(
"/:postId/:userId?t=inc",
tokenChecker,
postController.updateLikesComments
);
router.post(
"/:postId/:userId?t=dec",
tokenChecker,
postController.updateLikesComments
);
All of them work fine but when I use query in my URL, it's not working any more.
You don't specify query parameters in express routes like that. Just send them. Express can read it.
router.post(
"/:postId/:userId",
tokenChecker,
postController.updateLikesComments
);
// Notice that you don't need the other one.
and in your controller check the parameter
// controller's code
const t = req.query.t;
if (t === 'inc') {
// do what you want here
}
if (t === 'dec') {
// do what you want here
}
The goal is to have users enter in some information into a form and spit that out into a PDF. I'm using JSPDF to parse and create the PDF. I've successfully gotten my code to make a printable PDF, but in an effort to not have paper floating around the office, I made a cloud function to instead email that PDF to the customer.
Here is my code on the front end. maildoc is the pdf that I've made, it hasn't been printed or anything. So it only exists in memory.
mailDoc = mailDoc.output('datauri');
mailFunction += "&?data=" + mailDoc;
//axios request to the cloud function
axios.get(mailFunction).then( function (response) {
console.log(response);
}).catch(function (error) {
console.log(error)
})
And here is my code on the cloud function
exports.sendMail = functions.https.onRequest((req, res) => {
cors(req, res, () => {
// getting dest email by query string
//?dest= DestinationEmail
const dest = req.query.dest;
const data = req.query.data;
const mailOptions = {
from: 'whatever <whatever#hoobashaka.com>',
to: dest,
subject: "You're Equipment Return to HBCI", // email subject
attachments :[
{
filename: 'return.pdf',
contentType: 'application/pdf',
path: data,
}
],
};
return transporter.sendMail(mailOptions, (erro, info) => {
if(erro){
return res.send(erro.toString());
}
return res.send('Sended');
});
});
If I try and send the data via URI, I get a 413 error, probably because that URI is enormous. But I can't think of another way of sending that generated PDF to the function.
On your client, instead of uploading the file as a datauri, I'd instead use POST and send the PDF inside the request body (just as if you had submitted a file using a form).
mailDocBlob = mailDoc.output('blob');
const data = new FormData();
data.set('dest', someEmail);
data.append('file', mailDocBlob, 'return.pdf');
axios({
method: 'post',
url: 'https://your-cloud-function.here/sendMail',
data: data,
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
On the server you would handle the multipart form data using the busboy package.
const BusBoy = require('busboy');
exports.sendMail = functions.https.onRequest((req, res) => {
cors(req, res, (err) => {
if (err) {
// CORS failed. Abort.
console.log("CORS failed/rejected");
res.sendStatus(403); // 403 FORBIDDEN
return;
}
if (req.method !== 'POST') {
res.set('Allow', 'POST, OPTIONS').sendStatus(405); // 405 METHOD_NOT_ALLOWED
return;
}
let busboy = new BusBoy({headers: req.headers, limits: {files: 1}}); // limited to only a single file
const mailOptions = {
from: 'whatever <whatever#hoobashaka.com>',
to: dest,
subject: "Your Equipment Return to HBCI", // email subject - fixed typo
attachments: []
};
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
// add new file attachment
mailOptions.attachments.push({
filename: 'return.pdf',
contentType: 'application/pdf',
content: file, // file is a stream
});
})
.on('finish', () => {
if (mailOptions.attachments.length == 0) {
// not enough attachments
res.status(400).send('Error: not enough attachments');
return;
}
return transporter.sendMail(mailOptions, (erro, info) => {
if (erro) {
return res.status(500).send('Error: ' + erro.toString());
}
return res.send('Sent');
})
})
.on('error', (err) => {
console.error(err);
res.status(500).send('Error: ' + err.code);
});
req.pipe(busboy);
});
I'm trying to upload an image to an API server in iOS and I keep receiving a server error.
Below is my uploading code (in Swift) followed by the API code (in JavaScript).
func upLoadData(strUrl: String, productionImageData:Data?, parameters: [String : Any]?,completion:#escaping (NSDictionary?,Int)->()){
let url = strUrl
let headers: HTTPHeaders = [
"Content-type": "multipart/form-data"
]
Alamofire.upload(multipartFormData: { (multipartFormData) in
if parameters != nil{
for (key, value) in parameters! {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
}
if let productionData = productionImageData{
print(productionData.count)
multipartFormData.append(productionData, withName: "file", fileName: "imgData.jpg", mimeType: "image/jpg")
}
}, usingThreshold: UInt64.init(), to: url, method: .post, headers: headers) { (result) in
switch result{
case .success(let upload,_,_ ):
upload.responseJSON { response in
if let data = response.result.value as? NSDictionary {
print(data)
completion(data,(response.response?.statusCode)!)
}
else{
///USUALLY COMES IN THIS CLAUSE
print((response.response?.statusCode)!)
completion(nil, (response.response?.statusCode)!)
}
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
completion(nil,0)
}
}
//This is the API
JavaScript
function CoverImageUpload(req, res, next){
var id = sanitizer.sanitize(req.body.id);
var file_path = sanitizer.sanitize(req.files.file.path);
console.log(req)
fs.readFile(file_path, (err,data) => {
if (err) throw err;
photo.coverImageUpload(id, data)
.then(function(response){
console.log(response.result)
res.send(response)
})
.catch(err => res.send(err))
})
return next();
}
The actual result will basically respond with a json that includes a URL of where the image is stored. However, currently I'm receiving a HTML response with server error and I feel I have the wrong parameters/haven't set up the right call the the JavaScript API.
Is there a way to upload video to a server in react native?
I've looked into the react-native-uploader plugin on github, but it doesn't give any guidance on video uploads if it's even possible with that plugin.
Just use fetch for uploading
let formData = new FormData();
formData.append("videoFile", {
name: name.mp4,
uri: video.uri,
type: 'video/mp4'
});
formData.append("id", "1234567");
try {
let response = await fetch(url, {
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData
});
return await response.json();
}
catch (error) {
console.log('error : ' + error);
return error;
}
Here is another answer, using rn-fetch-blob in RN 0.57.8.
postVideo = (video,url) => {
RNFetchBlob.fetch('POST',url, {
'content-type': 'multipart/form-data',
"Accept":"multipart/form-data",
'access-token': AuthToken.token, //token from server
},[
//the value of name depends on the key from server
{name: 'video', filename: 'vid.mp4', data: RNFetchBlob.wrap(video.uri) },
]).then(response => response.json())
.then(response => {
if (response.status === 'success') {
alert("Upload success");
this.props.navigation.navigate('publish');
} else {
alert(response.msg);
}})
.catch((err) => {
alert(err);
})
}
Yes, it is possible.
you have to be running React Native 0.45.0 or higher, which do support accessing videos from camera roll.
you have to receive reference to image/video access from camera roll by calling CameraRoll.getPhotos(params) (more on this in docs)
then, use RNUploader.upload(...) to send assets to your serve (you need to link lib before!)