I am trying to set up "Cloudinary" for image uploads from my React app.
My submit function keeps responding with: "Bad Gateway 502" and "SyntaxError: Unexpected end of input".
I'm assuming something is wrong with my headers, but I can't find the issue...
handleFileSelect = (e) => {
this.formValid()
this.setState({
picture: e.target.files[0] })
}
submit(){
const CLOUDINARY_URL=
"https://api.cloudinary.com/v1_1/dvz27u2gu/image/upload"
const CLOUDINARY_UPLOAD_PRESET= "jshvp3nh"
const obj = Object.assign({}, this.state);
const formData = new FormData();
formData.append("file", obj.picture);
formData.append("upload_preset", CLOUDINARY_UPLOAD_PRESET);
fetch(CLOUDINARY_URL,{
mode: 'no-cors',
method:'post',
headers: { "Content-Type": "application/x-www-form-urlencoded"},
body:formData,
})
.then((res)=>{return res.json()})
.then(data=>console.log(data))
.catch(err=>console.log(err));
}
You can try something like the following:
<div><input type="file" onChange={this.submit}/></div>
submit = (e) => {
var file = e.target.files[0];
var data = new FormData();
data.append('upload_preset', 'jshvp3nh');
data.append('file', file);
data.append('cloud_name', 'dvz27u2gu');
const config = {
method: "POST",
body: data
};
var imgurl = "https://api.cloudinary.com/v1_1/dvz27u2gu/raw/upload";
fetch(imgurl, config)
.then(responseData => {
console.log('here');
console.log(JSON.stringify(responseData, null, 4));
console.log(responseData);
})}
This is how it worked for me.
const CLOUDINARY_URL= "https://api.cloudinary.com/v1_1/dvz27u2gu/image/upload"
const CLOUDINARY_UPLOAD_PRESET= "jshvp3nh"
const obj = Object.assign({}, this.state);
const formData = new FormData();
formData.append("file", obj.picture);
formData.append("api_key", "xx")
formData.append("api_secret", "xx")
formData.append("upload_preset", CLOUDINARY_UPLOAD_PRESET);
formData.append("timestamp", (Date.now() / 1000) | 0);
fetch(CLOUDINARY_URL,{
method:'POST',
body: formData,
})
.then((res)=>{return res.json()})
.then((data)=>{
obj.img_url_cloudinary=data.secure_url;
this.sendForm(obj);
}).catch(err=>console.log(err));;
Related
TDLR: Using s3 presigned post url to upload file to s3. Works fine on the browser but fails on the server.
I have a simple lambda function that generates presigned post url that can be consumed either in the browser or in the server.
During testing I noticed that the upload works fine one the browser but fails if I try to upload a file from a server even tho the code is identical.
The error i get is:
You must provide the Content-Length HTTP header
Detailed error:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>MissingContentLength</Code>
<Message>You must provide the Content-Length HTTP header.</Message>
<RequestId>JP75YMFARK0G3X5Z</RequestId>
<HostId>toHsKmxmVYYAtac94cQoy8wXoregKG3PNBm97c3gQewEmKxLggcumTAP882T/pJNWx/lxRgH98A=</HostId>
</Error>
Request failed with status code 411
I checked online and found many threads about this issue but unfortunately not a single suggestion helped me.
Code I am running in the server
const axios = require('axios');
const { createReadStream, readFileSync } = require('fs');
const FormData = require('form-data');
const getPostPresignedUrl = async () => {
var config = {
method: 'post',
url: LAMBDA_GET_URL,
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({
key: 'test-2.jpg',
fileType: 'image/jpeg',
}),
};
const {
data: { data },
} = await axios(config);
return data;
};
const uploadFileToS3 = async (fields, url) => {
const formData = new FormData();
Object.entries(fields).map(([key, value]) => {
formData.append(key, value);
});
const file = createReadStream('./test-1.jpg');
formData.append('file', file);
try {
const { data } = await axios({
url,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
});
} catch (error) {
if (error instanceof axios.AxiosError) {
console.log(error.response.data);
}
console.log(error.message);
}
};
const init = async () => {
const { fields, url } = await getPostPresignedUrl();
await uploadFileToS3(fields, url);
};
init();
Code I am running in the browser:
const form = document.getElementById('form');
const input = document.getElementById('file');
const getPostPresignedUrl = async (name) => {
var config = {
method: 'post',
url: LAMBDA_GET_URL,
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({
key: name,
fileType: 'image/jpeg',
}),
};
const {
data: { data },
} = await axios(config);
return data;
};
const uploadFileToS3 = async (fields, url, file) => {
const formData = new FormData();
Object.entries(fields).map(([key, value]) => {
formData.append(key, value);
});
formData.append('file', file);
try {
const { data } = await axios({
url,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
});
} catch (error) {
if (error instanceof axios.AxiosError) {
console.log(error.response.data);
}
console.log(error.message);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const file = input.files[0];
const data = await getPostPresignedUrl(file.name);
await uploadFileToS3(data.fields, data.url, file);
};
form.onsubmit = handleSubmit;
I am trying to send text and formData in one fetch call to a Node.js backend using multer.
I can send formData on its own with no issues, but when I try and add text, the api call stays 'pending'.
Here is my fetch call that works just with formData:
const handleImage = async (e) => {
var formData = new FormData();
let file = e.target.files[0];
formData.append("image", file);
try {
const upload = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_API}/uploadImage`,
{
method: "POST",
body: formData,
}
);
} catch (e) {
console.log("Something went wrong!");
}
};
Here is the same fetch call with text added that does not work:
const handleImage = async (e) => {
var formData = new FormData();
let file = e.target.files[0];
formData.append("image", file);
try {
const upload = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_API}/uploadImage`,
{
method: "POST",
body: {formData, userId}
}
);
} catch (e) {
console.log("Something went wrong!");
}
};
It also doesn't work if I try and user JSON.stringify().
I do believe that you can't send a formData and json body at the same time (maybe there is a way somehow i don't know)
because multer will just take the file from formdata and the other property will be set to req.body so if you want to send userId you can try
const handleImage = async (e) => {
var formData = new FormData();
let file = e.target.files[0];
formData.append("image", file);
formData.append("userId", userId);
try {
const upload = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_API}/uploadImage`,
{
method: "POST",
body: formData,
}
);
} catch (e) {
console.log("Something went wrong!");
}
};
I need to include the image as binary data in my uploading request using multipart form data, and it seems not working, any advise will be appreciated.
my code:
const [selectedFile, setSelectedFile] = useState(null);
const handleSubmit = async (event) => {
event.preventDefault();
const formData = new FormData();
formData.append('selectedFile', new Blob([selectedFile], { type: 'application/octet-stream' }));
const data = {
uploadLink,
formData,
};
const headers = {
'Content-Type': 'application/octet-stream' ,
Accept: 'application/vnd.vimeo.*+json;version=3.4',
};
try {
await axios
.post(`${backendPostPath}/thumbnail-upload`, data, {
headers,
})
.then((response) => {
applyThumbnial();
console.log(response);
});
} catch (error) {
console.log(error);
}
};
const handleFileSelect = (event) => {
setSelectedFile(event.target.files[0]);
};
include formData as axios data parameter instead of your data object, so you can also include uploadLink in the formData:
const formData = new FormData();
formData.append('selectedFile', new Blob([selectedFile], { type: 'application/octet-stream' }));
formData.append('uploadLink', uploadLink)
//...
await axios
.post(`${backendPostPath}/thumbnail-upload`, formData, {
headers,
})
I have a post method
uploadFile: async function () {
const formData = new FormData();
formData.append("file", this.file);
let url = `http://...`;
try {
this.source = axios.CancelToken.source();
const res = await axios.post(url, formData, {
headers: {
Authorization: "Token " + this.$store.getters.getToken,
"Content-Type": "multipart/form-data",
},
cancelToken: this.source.token,
});
} catch (error) {
}
}
and cancel method
cancelLoad: function () {
this.source.cancel('cancel upload');
},
The request was canceled, but after reloading my page, the file uploaded.
I've fixed it.
const CancelToken = axios.CancelToken;
let cancel;
const res = await axios.post(url, formData, {
headers: {...},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
}),
}...
cancel();
i have a redux-from submission, console log look like this
{
id: "x",
parentId: "b",
editing: true,
logo: FileList,
}
Logo FileList contains my uploaded file name and file, i think
0: File(19355) {name: "11964821.jpeg", lastModified: ......
using fetch to send to nodejs, image contain my files and above data
function Update(image) {
const requestOptions = {
method: 'POST',
headers: { ...authHeader(), 'Content-Type': 'application/x-www-form-urlencoded' },
body: JSON.stringify(image)
};
return fetch(`${apiUrl}/API`, requestOptions).then(handleResponse)
.then( data => { return data; });
}
but this data not receiving nodejs, because is tried re.file etc.. its shows undefined
app.post('/image', upload.single('logo'), function (req, res, next) {
})
include formdata
const onSubmit = (image, dispatch)=>{
var formData = new FormData();
formData.append('logo',image.logo[0]);
var imageNew = {...image,formData};
dispatch(imageActions.companyProfileLogoUpdate(imageNew)) ;
}
now log is
formData: FormData {}
id: "5c66478b0814720a4365fe72"
logo: FileList {0: File(19355), length: 1}
parentId: "5c66478b0814720a4365fe71"
let formData = new FormData();
formData.append('logo' , {{your image file}}
// upload file as
let result = await sendServerRequestForForm(url,formData);
function sendServerRequestForForm(url,data) {
var promise = new Promise(function(resolve) {
resolve($.ajax({
url,
method : 'POST',
data,
processData: false,
contentType: false,
success: function(data) {
return data
},
error: function (err) {
try{
let responseStatus = err.responseJSON
// watch your response
}catch (e) {
console.log('Field to get response');
}
}
}));
});
return promise
}
for fetch API you can try this
let formData = new FormData();
formData.append('logo', fileList[0]);
fetch(url, {
method: 'post',
body: data,
})
.then(…);
move formData to fetch file and remove header content type, Try this
function Update(image) {
var formData = new FormData();
formData.append('logo',image.logo[0]);
const requestOptions = {
method: 'POST',
headers: { ...authHeader() },
body: formData
};
return fetch(`${apiUrl}/API`, requestOptions).then(handleResponse)
.then( data => { return data; });
}
First thing is for using fetch api for post content-type header should match typeof body. since your body is json stringified your contentType header should be 'application/json' . more about this .
Second. since you want to upload an image which a file you should use FormData without requirement of setting contentType: like below:
let formData = new FormData();
formData.append('logo', image.logo[0]);
const requestOptions = {
method: 'POST',
body: formData
};
fetch(`${apiUrl}/API`, requestOptions)
.then(handleResponse)...