As I said, I want to convert that POST request with a file to JavaScript. This code sends a JSON request which contains an image file to server.
The Dart function is this (convert this to javascript):
Future postData(User user, VideoGame videoGame, File file) async {
Map data = {
'name': user.name,
'contact': user.contact,
'location': {
'country': user.country,
'state': user.state,
'city': user.city
},
'videoGame': {
'name': videoGame.name,
'type': videoGame.type,
'console': videoGame.console,
}
};
try {
String _url = baseUrl + 'insertData';
var uri = Uri.parse(_url);
var request = http.MultipartRequest('POST', uri)
..headers.addAll({'Content-type': 'multipart/form-data', 'Accept': 'multipart/form-data'})
..fields.addAll({'data': json.encode(data)});
request.files.add(
http.MultipartFile(
'image',
file.readAsBytes().asStream(),
file.lengthSync(),
filename: file.path.split("/").last
),
);
var response = await request.send();
print('Status ${response.statusCode}');
if (response.statusCode == 200) {
final respStr = await response.stream.bytesToString();
print(jsonDecode(respStr));
MyALertKey
.currentState
?.setState((){});
}
} catch (e) {
print("Video Games POST error => ${e.toString()}");
}
}
Because the server written in Python I couldn't see that this file sends to server (request full body).
I have written this in JavaScript but it doesn't work.
const handleSubmit = async (e) => {
e.preventDefault();
var data = new FormData()
var blob = new Blob([JSON.stringify({
name: somevalue,
contact: somevalue,
location: {
country: somevalue,
state: somevalue,
city: somevalue
},
videoGame: {
name: somevalue,
type: somevalue,
console: somevalue,
}
})],{
type: 'application/json'
})
data.append('data',blob)
data.append('image',file_from_input)
try {
const res = await fetch('url',{
method:'POST',
cache: 'default',
mode: 'no-cors',
headers: {
'Content-Type': 'multipart/form-data'
},
body: data
})
let data_ = await res.json()
console.log(data_)
} catch (e) {
console.log(e)
}
console.log(res.status) // will be 400 bad request
}
Please help me. Thanks.
Related
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;
})
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;
I have some code that looks like this in Next JS
const resApp = await fetch('/api/club/createsignalapp', {
body: JSON.stringify({
name: event.target.name.value,
}),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
})
const appResult = await resApp.json()
--createsignalapp
export default async (req, res) => {
var mydata
var createApp = function (data) {
var headers = {
'Content-Type': 'application/json; charset=utf-8',
Authorization: `Basic APIKKEY`,
}
var options = {
host: 'onesignal.com',
port: 443,
path: '/api/v1/apps',
method: 'POST',
headers: headers,
}
var https = require('https')
var myreq = https.request(options, function (myres) {
myres.on('data', function (data) {
mydata = JSON.parse(data)
res.statusCode = 200
res.json({
response: {
boolean: true,
alert: '',
message: '',
},
data: mydata
})
})
})
myreq.on('error', function (e) {
console.log(e)
})
myreq.write(JSON.stringify(data))
myreq.end()
}
var message = {
name: req.body.name
}
createApp(message)
}
This hits the error API resolved without sending a response for /api/club/createsignalapp, this may result in stalled requests.
I'm not sure how to do this correctly as i'm getting confused with the awaits and asyncs and requests everywhere.
Happy to hear suggestions.
Thanks
Why is this request a bad request, I have sent the same request in postman, using raw data, and header content-type applications/json and it works.
But in my axios request, I get bad request
const update = dispatch => {
return async (name, email, phone, picture, Age, Blood, Gender, Height, Weight, id) => {
const data = new FormData();
data.append('name', name);
data.append('email', email);
data.append('phone', phone);
data.append('Age', Age);
data.append('Blood', Blood);
data.append('Gender', Gender);
data.append('Height', Height);
data.append('Weight', Weight);
data.append("picture", {
type: 'image/jpg',
uri: picture,
name: 'profilepic.jpg'
});
const config = {
method: 'put',
url: `http://c256474d.ngrok.io/api/userregister/24`,
data: data,
headers: { 'content-type': 'application/json' }
}
await axios(config)
navigate('UserAccount')
}
}
This is the server side code, this works when tested with postman. It doesn't work when send with form-data, but works when the body is raw and header of application/json
public function update(Request $request, $id)
{
// dd($request->all());
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'string|email|max:255',
'phone' => 'string|min:6',
'Age' => 'string',
'Blood' => 'string',
'Gender' => 'string',
'Height' => 'string',
'Weight' => 'string',
'record' => 'string'
]);
if($validator->fails()){
return response()->json($validator->errors()->toJson(), 400);
}
$doc = User::find($id);
if($request->hasFile('picture')){
// Get filename with the extension
$filenameWithExt = $request->file('picture')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('picture')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
// Upload Image
$path = $request->file('picture')->storeAs('public/images', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
$doc->name = $request->input('name');
$doc->email = $request->input('email');
$doc->phone = $request->input('phone');
if($request->hasFile('picture')){
$doc->picture = $fileNameToStore;
}
$doc->save();
return response()->json([
'message' => 'Success',
]);
}
We can't know why the server thinks the data is bad because you haven't shared the server-side code that makes that determination.
It's a fairly reasonable bet that including 'content-type': 'application/json' in the headers and then not sending JSON in the body isn't helping though.
FormData objects are used to generate multipart/form-data request bodies, not application/json.
If you want to send JSON then you need to generate JSON:
const data = {
name: name,
email: email,
phone: phone,
Age: Age,
Blood: Blood,
Gender: Gender,
Height: Height,
Weight: Weight,
picture: {
type: "image/jpg",
uri: picture,
name: "profilepic.jpg"
}
};
const config = {
method: "put",
url: `http://c256474d.ngrok.io/api/userregister/24`,
data: JSON.stringify(data),
headers: { "content-type": "application/json" }
};
Change your header to
{ headers: { 'Content-Type': 'multipart/form-data' } }
You are not sending JSON Data.
I want use my api to send e-mail in some cases,the service (infobip) docs show an example in JS but it don't work in my api with nodejs and expressjs. Can someone help me?
/*----Sending fully featured email----*/
function createFormData(data) {
var formData = new FormData();
for (var key in data) {
formData.append(key, data[key]);
}
return formData;
}
//Dummy File Object
var file = new File([""], "filename");
var data = {
'from': 'Sender Name <from#example.com>',
'to': 'recipient1#example.com',
'subject': 'Test Subject',
'html': '<h1>Html body</h1><p>Rich HTML message body.</p>',
'text': 'Sample Email Body',
'attachment': file,
'intermediateReport': 'true',
'notifyUrl': 'https://www.example.com/email/advanced'
};
var xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.addEventListener('readystatechange', function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open('POST', 'https://{base_url}.infobip.com/email/1/send', false);
xhr.setRequestHeader('authorization', 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==');
xhr.setRequestHeader('accept', 'application/json');
xhr.send(createFormData(data));
You should use https from nodejs.
Here an example code to getting started. For infopib it seems to be so normal Post request.
I tried to create an account on this page, but registration seems to can be completed only over sales. So I couldn't provide a working example...
This is why I can only provide a general example how to make an https POST call, which should be a good starting point to develop your solution:
const https = require('https')
const data = JSON.stringify({
todo: 'Buy the milk'
})
const options = {
hostname: 'yourURL.com',
port: 443,
path: '/todos',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()