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;
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;
})
I am attempting to upload a file using the Node example provided in the HubSpot docs.
I am receiving 415(Unsupported media type). The response says I am sending the header application/json even though I am setting multipart/form-data.
const uploadFile = async () => {
const postUrl = `https://api.hubapi.com/filemanager/api/v3/files/upload?hapikey=${HAPI_KEY}`;
const filename = `${APP_ROOT}/src/Files/Deal/4iG_-_CSM_Additional_Capacity/test.txt`;
const headers = {
'Content-Type': 'multipart/form-data'
}
var fileOptions = {
access: 'PUBLIC_INDEXABLE',
overwrite: false,
duplicateValidationStrategy: 'NONE',
duplicateValidationScope: 'ENTIRE_PORTAL'
};
var formData = {
file: fs.createReadStream(filename),
options: JSON.stringify(fileOptions),
folderPath: '/Root'
};
try {
const resp = await axios.post(postUrl, formData, headers); // API request
console.log(resp.data)
} catch (error) {
console.log("Error: ", error);
}
}
Can you see what the problem is or recommend a better way of uploading the file?
Thanks!
The Node example you link to uses the (deprecated) request module, not Axios.
To use Axios (source) you would rewrite that as:
const FormData = require('form-data');
const form = new FormData();
form.append('file', fs.createReadStream(filename));
form.append('options', JSON.stringify(fileOptions));
form.append('folderPath', '/Root');
const config = { headers: form.getHeaders() };
axios.post(postUrl, form, config);
We can Run API in Postman and check NodeJs - Axios Detail in Postman Code Snippet and I Think That's the Better way for this.
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const uploadFile = async () => {
try {
let data = new FormData();
data.append('folderPath', '/Root');
form.append('file', fs.createReadStream(`${APP_ROOT}/src/Files/Deal/4iG_-_CSM_Additional_Capacity/test.txt`));
data.append('options', JSON.stringify({
access: 'PUBLIC_INDEXABLE',
overwrite: false,
duplicateValidationStrategy: 'NONE',
duplicateValidationScope: 'ENTIRE_PORTAL'
}));
var config = {
method: 'post',
url: `https://api.hubapi.com/filemanager/api/v3/files/upload?hapikey=${HAPI_KEY}`,
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
};
const resp = await axios(config); // API request
console.log(resp.data)
} catch (error) {
// error
}
}
I am trying to upload images from desktop but the error for multipart boundary not found. How to set a boundary for image uploading? This is my first time doing image uploading so please advice.
html event listener when user upload image
document.getElementById('image-file').addEventListener('change',
async (e) => {
const file = e.target.files[0]
const bodyFormData = new FormData()
bodyFormData.append('image', file)
showLoading()
const data = await uploadProductImage(bodyFormData)
hideLoading()
if (data.error) {
showMessage(data.error)
} else {
showMessage('Image Uploaded Successfully.')
console.log(data)
document.getElementById('image').value = data.image
}
})
},
api.js - posting action
export const uploadProductImage = async (bodyFormData) => {
const options = {
method: 'POST',
body: bodyFormData,
headers: {
'Content-Type': 'multipart/form-data',
},
}
try {
const response = await fetch(`${apiUrl}/api/uploads`, options)
const json = await response.json()
if (response.status !== 201) {
throw new Error(json.message)
}
return json
} catch (err) {
console.log('Error in upload image', err.message)
return { error: err.message }
}
}
uploadroute.js - for uploading image
import express from 'express'
import multer from 'multer'
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, 'uploads/')
},
filename(req, file, cb) {
cb(null, `${Date.now()}.png`)
},
})
const upload = multer({ storage })
const router = express.Router()
router.post('/', upload.single('image'), (req, res) => {
res.status(201).send({ image: `/${req.file.path}` })
})
export default router
When you're sending a form with fetch in the frontend, don't set Content-Type header yourself. If you do, it won't have the form boundary and the multipart/form-data request will be parsed incorrectly in the backend.
You can omit the header because the browser will set it for you, which includes a unique boundary. For example:
Your header: Content-Type=multipart/form-data;
Browser's header: Content-Type=multipart/form-data; boundary=------WebKitFormBoundaryg7okV37G7Gfll2hf--
In your case:
const options = {
method: 'POST',
body: bodyFormData,
}
const response = await fetch(`${apiUrl}/api/uploads`, options)
this is my code :
Express Routes:
router.route('/block')
.post(controller.ticketBlocking);
Express Controller:
const axios = require('axios');
const OAuth = require('oauth-1.0a');
const crypto = require('crypto');
const ticketBlocking = (req, res) => {
const data = JSON.stringify({
source = req.body.source
});
const oauth = OAuth({
consumer: {
key: '....', //Hided the key
secret: '....', //Hided the secret
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return crypto.createHmac('sha1', key).update(base_string).digest('base64');
}
});
const request_data = {
url: 'http://link.vvv/blockTicket',
method: 'post',
};
axios({
method: request_data.method,
url: request_data.url,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
...oauth.oauth.toHeader(oauth.oauth.authorize(request_data)),
},
data : data
})
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
} else if (error.request) {
console.log(error.request);
} else {
console.log('Error', error.message);
}
console.log(error.config);
});
};
the npm package which am using is - "oauth-1.0a"
The problem am facing is, when i use GET method with different end point, i get an output but when ever i use POST method am getting an empty error with status code 500
I dont know where is the mistake, am using oauth1.0a for authorization, please help !
presently I am attempting to make 2 different api calls one after the other within 1 java/nodejs script. It seems after my first function runs successfully, the second one errors with the following:
FetchError: request to failed, reason: socket hang up;
type: 'system',
errno: 'ECONNRESET',
code: 'ECONNRESET'
Below is a code snippet of what I have tried thus far:
const fetch = require("node-fetch");
const formData = require("form-data");
const fs = require("fs");
//const express = require("express");
var apiName = "<LOCAL SYSTEM FILE TO UPLOAD>";
var lookupName = "<LOCAL SYSTEM FILE TO UPLOAD>";
var accessToken = "Bearer <ACCESS TOKEN>";
var url = '<URL API #1>';
var url2 = '<URL API #2>;
var headers = {
'Accept': 'application/json',
'Authorization': accessToken,
};
const form = new formData();
const buffer2 = fs.readFileSync(lookupName);
const buffer = fs.readFileSync(apiName);
const uploadAPI = function uploadAPI() {
form.append("Content-Type", "application/octect-stream");
form.append('file', buffer);
fetch(url, {method: 'POST', headers: headers, body: form})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
};
const uploadLookup = function uploadLookup() {
form.append("Content-Type", "application/octect-stream");
form.append('file', buffer2);
fetch(url2, {method: 'PUT', headers: headers, body: form})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
};
if (!apiName !== true) {
uploadAPI()
} else {}
if (!lookupName !== true) {
console.log("Uploading Lookup File");
uploadLookup()
} else {}
I tried using a "setTimeout" function which does not seem to work as I would have liked it to. My best guess is each API call would need to be it's own separate socket connection? Any help with getting me in the right direction is appreciated.
Promise.all([
fetch(url),
fetch(url2)
]).then(function (res) {
// Get a JSON object from each of the responses
return res.json();
}).then(function (data) {
// do something with both sets of data here
console.log(data);
}).catch(function (error) {
// if there's an error, log it
});