axios vs fetch throwing error on file upload - javascript

I am using fetch instead of axios in my react project
my this method working fine with the axios to upload an image on the server
Upload image function
<Upload customRequest={dummyRequest} className="upload-btn-container" onChange={onChange}>
<Button className="btn custom-upload-btn">Upload Image</Button>
</Upload>
const uploadPicture = async (data) =>{
const value = await getUploadPicture(data)
if(value.value.data.status){
await addImage(value.value.data.data)
}
}
const onChange = async (info) => {
for (let i = 0; i < info.fileList.length; i++) {
const data = new FormData();
data.append('file', info.fileList[i]);
data.append('filename', info.fileList[i].name);
setImgName(info.fileList[i].name)
let value = await uploadPicture(data);
}
};
return axios({
method: 'post',
url: `${NewHostName}/upload`,
headers: {
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('authToken')
},
data:data
})
.then(response => {
return response
}).catch(err => {
console.log("err", err)
})
whereas when I do same with the fetch it throws me error on the backend "Cannot read property of split of undefined"
return fetch(`${NewHostName}/upload`, {
method: "post",
headers: {
"Content-Type": "application/json",
Authorization: localStorage.getItem('authToken'),
},
body: JSON.stringify(data),
// body :data
})
.then((res) => {
return res.json();
})
.then((payload) => {
return payload;
})
.catch((err) => {
throw err;
})
Not sure what is the reason behind this
this is my backend upload api
const handler = async (request, reply) => {
try {
const filename = request.payload.filename
const fileExtension = filename.split('.').pop()
AWS.config.update({
accessKeyId: Config.get('/aws').accessKeyId,
secretAccessKey: Config.get('/aws').secretAccessKey,
region: Config.get('/aws').region
})
const s3 = new AWS.S3({
params: {
Bucket: Config.get('/aws').bucket
}
})
const Key = `/${shortid.generate()}.${fileExtension}`
const obj = {
Body: request.payload.file,
Key,
ACL: 'public-read'
}
s3.upload(obj, async (err, data) => {
if (err) {
return reply({ status: false, 'message': err.message, data: '' }).code(Constants.HTTP402)
} else if (data) {
return reply({ status: true, 'message': 'ok', data: data.Location }).code(Constants.HTTP200)
}
})
} catch (error) {
return reply({
status: false,
message: error.message,
data: ''
})
}
}

data is a FormData object.
In your original code you are lying when you say 'Content-Type': 'application/json'. Possibly Axios recognises that you've passed it a FormData object and ignores your attempt to override the Content-Type.
Your fetch code, on the other hand, says body: JSON.stringify(data) which tries to stringify the FormData object and ends up with "{}" which has none of your data in it.
Don't claim you are sending JSON
Don't pass your FormData object through JSON.stringify

For image upload you not use JSON.stringify(data).You can try with formData and append an image file with form data.
var formdata = new FormData();
formdata.append("image", data);

Did you check that
const filename = request.payload.filename
exists?
Is the key really payload? The following does not make any changes to your code:
.then((payload) => {
return payload;
})

Related

how to fix uri undefined error when trying to send request

when I'm trying to call the request in front node, I'm getting error in my backend node " RequestError: Error: Invalid URI "undefined"" , it seems like backend node request is not getting the data form my frontend node request.
knowing that uploadLink already have a value and in my browser console the frontend request looks ok
my backend request code
const ThumbnailUpload = async (req, res) => {
const { Uploadlink } = req.body;
const { selectedFile } = req.body;
const clientServerOptions = {
uri: `${Uploadlink}`,
body: JSON.stringify({
name: selectedFile,
}),
method: 'PUT',
headers: {
'Content-Type': ' application/json',
Accept: 'application/vnd.vimeo.*+json;version=3.4',
Authorization: getVimeoAuthorization(),
},
};
request(clientServerOptions, function (error, response) {
if (error) {
res.send(error);
} else {
const body = JSON.parse(response.body);
res.send(body);
}
console.log(Uploadlink);
});
};
and my frontend code is
const handleSubmit = (event) => {
event.preventDefault();
const formData = new FormData();
formData.append(
'selectedFile',
new Blob([selectedFile], { type: 'image/jpg, image/png, or image/gif' }),
);
formData.append('uploadLink', uploadLink);
const headers = {
'Content-Type': 'image/jpg, image/png, or image/gif',
Accept: 'application/vnd.vimeo.*+json;version=3.4',
};
try {
axios
.post(`${backendPostPath}/thumbnail-upload`, formData, {
headers,
})
.then((response) => {
applyThumbnial();
console.log(response);
});
} catch (error) {
console.log(error);
}
};
any advise ?
change:
const { Uploadlink } = req.body;
to:
const { uploadlink } = req.body;
make variable consistent throughout the code
EDIT
also, since you're uploading a file, you need to use upload middleware before request handler, and file will be within req.file:
route.post('/thumbnail-upload', upload.single('selectedFile'), ThumbnailUpload);
//... handler..
const selectedFile = req.file;

Can't save state in React while POST API request

I have handleSubmit function that send two POST request, one for img upload and one for other information. I want to take the response from the img upload request and take the 'filename' and then store it in state so I can sent it with the other POST request.
Here is my Request Options
const postOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.serviceToken}`
},
body: JSON.stringify({
p_emp_id: empId,
p_pr_doc_type: docType,
p_from_date: fromDate,
p_to_date: toDate,
p_doc_number: docNumber,
p_addres: address,
p_addres_en: addressEN,
p_doc_store: docPath,
p_creator_id: creator,
p_org_id: org
})
};
Then here is my Handle Submit function
const handleSubmit = async (e) => {
e.preventDefault();
const data = new FormData();
data.append('file', selectedFiles);
await fetch(`${config.apiHost}single/`, {
method: 'POST',
body: data
})
.then((res) => res.json())
.then((img) => setDocPath(img.filename))
.catch((err) => {
console.log(err.message);
});
setEditOpen(false);
fetch(`${config.apiHost}api/employees/info/pr_docs/new/`, postOptions);
console.log(postOptions.body);
};
My state docPath stays empty while I'm trying to submit so after that I can't see it in my request.
you can refactor your code to this and lets see if it works;
let postOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.serviceToken}`
},
body: {
p_emp_id: empId,
p_pr_doc_type: docType,
p_from_date: fromDate,
p_to_date: toDate,
p_doc_number: docNumber,
p_addres: address,
p_addres_en: addressEN,
p_creator_id: creator,
p_org_id: org
}
};
for the handle submit it can be
const handleSubmit = async (e) => {
e.preventDefault();
const data = new FormData();
data.append('file', selectedFiles);
await fetch(`${config.apiHost}single/`, {
method: 'POST',
body: data
})
.then((res) => res.json())
.then((img) => {
const postOptionsBody = {...postOptions.body, p_doc_store : img.filename }
postOptions = {...postOptions, body : JSON.stringify(postOptionsBody) }
setDocPath(img.filename)
})
.catch((err) => {
console.log(err.message);
});
setEditOpen(false);
fetch(`${config.apiHost}api/employees/info/pr_docs/new/`, postOptions);
console.log(postOptions.body);
};

React native, write xml string to .xml file and send it to server

I'm trying to send xml string as a .xml file to server, as I able to create .xml file and wrote data in it with the help of react-native-fs but I unable to send it to api. I think it's not picking up the path. can anyone tell me how to properly do that.
Here is my code
const getToken = async () => {
updateState({isLoading: false});
const xml = await onJsonToXmal();
//create path for that xml file
const path = RNFS.DocumentDirectoryPath + '/test.xml';
// write xml into that file
RNFS.writeFile(path, xml, 'utf8')
.then((success: any) => {
// console.log(success, 'success');
})
.catch((err: any) => {
// console.log(err.message);
});
const checksum = md5(xml);
const formData = new FormData();
formData.append('file', {
uri: path,
type: 'xml',
name: 'demo.xml',
});
// formData.append('checksum', checksum);
axios({
method: 'post',
url: 'some url',
headers: {
'Content-Type': 'multipart/form-data',
Authorization:
'Bearer some token',
},
data: {
file: formData,
checksum,
},
})
.then(res => {
console.log(res.data);
updateState({isLoading: false});
})
.catch(error => {
console.log(error);
Alert.alert(`${error}`);
updateState({isLoading: false});
});
};
const onJsonToXmal = () => {
const data = dummyData; //dataForXml
const res = toXML(data);
return res;
};
thank you

Formidable returns null and two empty objects even though I am passing the correct FormData File image

I have the following code that happens on submit of a form
data contains the File, and it console's just fine. When I pass it to formidable in next JS it returns empty objects for Field and Files, and can't seem to figure out why.
const formData = new FormData();
formData.append("image", data.picture[0], data.picture[0].name);
console.log(data.picture[0]);
console.log(formData);
console.log(formData.get("image"));
const res = await fetch("../api/image", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
});
import formidable from "formidable";
// first we need to disable the default body parser
export const config = {
api: {
bodyParser: false,
},
};
export default async function image(req, res) {
const form = new formidable.IncomingForm();
form.uploadDir = "./";
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
console.log(err);
console.log(fields);
console.log(files);
});
//console.log(form);
// cloudinary.uploader.upload(`${body}`, function (error, result) {
// console.log(result, error);
// });
try {
// const result = req.body;
res.status(200).send({ message: "hello world" });
} catch (error) {
console.error(error);
res.status(error.requestResult.statusCode).send(error.message);
}
}
Ended up using axios, no idea why it works over fetch, and I tried the content type change in fetch as well
var formData = new FormData();
formData.append("image", data.picture[0], data.picture[0].name);
axios.post('../api/image', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})

getting requested files as an empty array in Laravel API from javascript

here is my javascript form handler
where i get data from the form to send it as request to API
import { Store } from './http/requests.js';
$(document).ready(function () {
$('#form_submit').submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
Store(formData);
});
});
js requests file handler
where i use customized post,get functions to send data with options that i provide on it
import { get, post } from '../helper.js';
let pageName = window.location.pathname;
pageName = pageName.slice(1, pageName.length - 5);
export const Store = (value) => {
switch (pageName) {
case 'add_car':
post('user/create_car', value, true, 'multipart/form-data')
.then((res) => {
console.log(res);
return res;
})
.catch((err) => console.log(err));
default:
break;
}
};
then the helper file where i use fetch get,post with option that i receive from "requests.js" file and provide it here
import { Local as loc } from './localStorage.js';
const API_URL = 'http://127.0.0.1:8000/api';
// token if exists in localStorage
const token = loc('get', 'token');
// POST Request
export const post = (
url,
formData,
auth = false,
type = 'application/json',
providedToken = token,
) => {
return fetch(`${API_URL}/${url}`, {
method: 'POST',
body: JSON.stringify(formData),
headers: {
'Content-Type': type,
Authorization: auth ? `Bearer ${providedToken}` : null,
},
})
.then((res) => res.json())
.then((res) => {
console.log(res);
return res;
})
.catch((err) => console.log(err));
};
and finally the Laravel API Cotroller where i tried to debug the issue
public function create_car(Request $request)
{
return (response()->json([
"files" => $_FILES,
"all Request data" => $request,
]));
}
the response i get when i send data from javascript to Laravel API
API gives me back this empty object as a response
it's seems like fetch has a problem ... anyway i just replaced fetch library with axios and everything runs perfectly
here is what i did on helper.js file
// POST Request
export const post = (
url,
formData,
auth = false,
type = 'application/json',
providedToken = token,
) => {
return axios({
method: 'POST',
url: `${API_URL}/${url}`,
data: formData,
headers: {
'Content-Type': type,
Authorization: auth ? `Bearer ${providedToken}` : null,
},
})
.then((res) => {
console.log(res);
return res.data;
})
.catch((err) => console.log(err.data));
};

Categories