Cannot update picture but getting 200 status - javascript

I would like to update a profile picture. The problem is when I send the image through axios to my server I get a 200 message. However, the profile picture is not updated.
I know the issue has something to do with my frontend code because when it try to upload a picture using Postman, the image is correctly updated.
This is the code I am using to send the image:
const handleSubmit = e => {
e.preventDefault();
let profileData = new FormData()
profileData.append('profilePic', {
uri: fileDataURL,
type: 'multipart/form-data',
name: 'profile_pic.png',
});
updateProfilePic(profileData, updatedProfileInfo.user_id)
}
and the axios request sending the image to the server:
const updateProfilePic = (profilePicData, user_id) => {
console.log('formData contains', ...profilePicData)
const headers = {
'accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.8',
'Content-Type': `multipart/form-data`,
}
const base_url = 'http://127.0.0.1:8000/update_profile/'
axios.patch(`${base_url}${user_id}/`,profilePicData, {
headers,
})
.then( res => {
console.log('resp', res)
})
}
This is what I have in fileDataURL:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/...
In a nutshell I know that everything that happens before the code I have shown is working, I upload a picture, I get the image base64 string and append that to profileData

Related

Sending formData to API in reactjs

I am using html2canvas to convert HTML to images.
So whenever the user submits the form, I am trying to send the image as blob and other details to the API using formData.
I am sending formData to the API to process the submitted data.
When user click on submit button, below code is responsible.
function handleReport(target = 'body') {
html2canvas(document.querySelector(target))
.then((canvas) => {
let pngUrl = canvas.toDataURL(); // PNG is the default
fetch(pngUrl)
.then((res) => res.blob())
.then((blob) => {
const formData = new FormData();
formData.append('images', [blob]);
// textarea content
formData.append('description', textAreaValue);
// user device info
formData.append('device[platform]', device.payload.platform);
formData.append('device[name]', device.payload.name);
formData.append('device[version]', device.payload.version);
formData.append('device[ip]', device.payload.ip);
formData.append('device[id]', device.payload.id);
formData.append('device[app_version]', device.payload.app_version);
formData.append('device[device_token]', device.payload.device_token);
dispatch(actions.contactUs(util.getApiToken(), util.getToken(), formData));
});
})
.catch((error) => {
console.log(error);
});
}
action definition :
export function contactUs(apitoken, token, payload) {
return {
[RSAA]: {
endpoint: `${API_ENDPOINT}/contact-us?api_token=${apitoken}`,
headers: {
...AUTH_HEADERS,
Authorization: `Bearer ${token}`,
},
method: 'POST',
body: payload,
// body: JSON.stringify(payload),
types: [
types.CONTACT_US_REQUEST,
types.CONTACT_US_RECEIVE,
],
},
};
}
Given below is the screenshot (not full screenshot) of payload (what user sent after clicking submit button) in Chrome browser
and this is the response I am getting from API
What is my problem !
I am sending all required keys (refer formData) but don't why am I getting error like :
description field is required
My header content is -
AUTH_HEADERS = {
'X-Authorization': X_AUTHORIZATION,
'Content-Type': 'application/json',
};
I just resolved my issue by removing 'Content-Type': 'application/json' which I was sending.
Now I am sending request to API without header.
headers: {
'X-Authorization': X_AUTHORIZATION,
Authorization: `Bearer ${token}`,
},
Now everything is working is fine.

How can i upload image to server using axios in react native?

I want to upload an image file to the server in react native, how can i do so?
Here is my code :
In my index.js Which is my entry point I have set axios default configurations :
axios.defaults.baseURL = BaseUrl;
axios.defaults.headers.common['Content-Type'] = 'application/json';
axios.defaults.headers.common['Accept'] = 'application/json';
Now in my profileEdit.js, where I need to upload a profile image
let data = new FormData();
data.append('profile_picture',
{uri: imageResponse.uri, name: imageResponse.fileName, type: 'image/jpg'});
// imageResponse is a response object that I m getting from React native ImagePicker
axios.post('profile/picture/', data,
{
headers: {
"Authorization": "JWT " + this.state.token,
'content-type': 'multipart/form-data',
}
}).then(response => {
console.log('Profile picture uploaded successfully', response);
}).catch(error => {
console.log('Failed to upload profile image', error);
console.log('Error response',error.response);
});
But this giving me network error, while other APIs are working fine.
I followed the solution given here How to upload image to server using axios in react native?
This is the error response I am getting.
And my request header is like this
I don't want to use any other package such as react native fetch blob
More links that I followed :
axios post request to send form data
Can anyone please tell me where I m doing wrong or how shall I approach to this problem. ty
I think your header for the Axios POST request may be incorrect since you're using a FormData() constructor to store your image data:
You may want to try the following instead:
let data = new FormData();
data.append('profile_picture',{
uri: imageResponse.uri,
name: imageResponse.fileName,
type: 'image/jpg'}
);
axios.post('profile/picture/', data,
{
headers: {
'content-type': `multipart/form-data; boundary=${data._boundary}`,
...data.getHeaders()
}
}
)
For me simply work
const oFormData = new FormData();
oFormData.append("image", {
uri: images.uri,
type: images.type,
name: images.fileName
});
axios.post(servicesUrl.imageupload, oFormData);

How to send image from image Uri through HTTP request? (React Native and Django Backend)

I’m using Expo’s image picker and I’m getting this output:
Object {
"cancelled": false,
"height": 468,
"uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540jbaek7023%252Fstylee/ImagePicker/9a12f0a3-9260-416c-98a6-51911c91ddf4.jpg",
"width": 468,
}
I could render my image, but I just realized that the URL is the phone’s local URI.
I’m using Redux-Thunk and Axios to send HTTP POST request:
export const sendPost = ( imageUri, title, content ) => async dispatch => {
let response = await axios.post(`${ROOT_URL}/rest-auth/registration/`, {
image, <<<<- I can't put image uri here :( it's LOCAL path
title,
content
})
if(response.data) {
dispatch({ type: POST_CREATE_SUCCESS, payload: response.data.token })
} else {
dispatch({ type: POST_CREATE_FAIL })
}
}
UPDATE I changed a request call
let headers = { 'Authorization': `JWT ${token}`};
if(hType==1) {
headers = { 'Authorization': `JWT ${token}`};
} else if (hType==2) {
headers = { 'Authorization': `Bearer ${token}`};
}
let imageData = new FormData();
imageData.append('file', { uri: image });
let response = await axios.post(`${ROOT_URL}/clothes/create/`, {
image: imageData,
text, bigType, onlyMe ...
}, {headers});
!! sorry for the complication but image variable name; image is uri for the image. I didn't want to change the name of original variable name
and on server, it's printing
'image': {'_parts': [['file', {'uri': 'file:///data/user/0/host.exp.exponent
/cache/ExperienceData/%2540jbaek7023%252Fstylee/
ImagePicker/78f7526a-1dfa-4fc9-b4d7-2362964ab10d.jpg'}]]}
I found that gzip compression is a way to send image data. Does it help?
Another option is to convert your image to base64 and send the string. Downsize is that usually the base64 strings has a bigger size than the image itself.
Something like this:
function readImage(url, callback) {
var request = new XMLHttpRequest();
request.onload = function() {
var file = new FileReader();
file.onloadend = function() {
callback(file.result);
}
file.readAsDataURL(request.response);
};
request.open('GET', url);
request.responseType = 'blob';
request.send();
}
It has to be a local URI, there's no issues with that, how else are you going to point to the image.
Now to upload the image you should first wrap it inside of FormData:
// add this just above the axios request
let img = new FormData();
img.append('file', { uri: imageUri });
Then inside of your axios request body add:
image: img,
EDIT: This question in it's current form is unanswerable.
I'm using the same Expo’s image picker with React-native in one of my projects as OP and everything works just fine, there's no issues with FormData.
After having talked with OP in a stackoverflow chat, couple of days ago, and stripping the request down to just an image, the server started throwing encoding errors:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 168: invalid start byte
So the issue is with OP's Django backend not being setup correctly in parsing the image, and not with the sending of the image itself - which makes the question unanswerable.
you cant use react-native-fetch-blob .....
import RNFetchBlob from " react-native-fetch-blob"
PostRequest(PATH){
RNFetchBlob.fetch('POST', "[URL]", {
"x-session-id": "SESSION_ID", //or Custom headers
'Content-Type': 'multipart/form-data',
}, [
{ name: 'image', filename: 'vid.jpeg', data: RNFetchBlob.wrap(PATH) },
// custom content type
]).then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
// error handling ..
})
}
}
for reference react-native-fetch-blob

Retrieve then POST a photo to a Foursquare Checkin with Axios

I'm trying to retrieve, then POST a JPEG image to Foursquare's https://api.foursquare.com/v2/photos/add endpoint using Axios in Node. I've tried a few methods with Axios (and Postman) but always receive the same error response of Missing file upload:
{
"meta": {
"code": 400,
"errorType": "other",
"errorDetail": "Missing file upload",
"requestId": "NNNNNNNNNNNNNNNNNNNNN" // not the true requestId
},
"notifications": [
{
"type": "notificationTray",
"item": {
"unreadCount": 0
}
}
],
"response": {}
}
The image is created using the Google Static Map API and retrieved with an Axios GET request:
const image = await axios.get(imageURL, {
responseType: "arraybuffer"
});
which is wrapped in an async function and successfully returns a buffer. The data is read into a Buffer and converted to a string:
const imageData = new Buffer(image, "binary").toString();
Here's an example imageData string. I've also tried converting the string to base64.
This string is then POSTed to the Foursquare endpoint:
const postPhoto = await axios.post(
"https://developer.foursquare.com/docs/api/photos/add?
checkinId=1234&
oauth_token=[TOKEN]&
v=YYYYMMDD",
imageData,
{
headers: { "Content-Type": "image/jpeg" }
}
);
where the checkinId, oauth_token and v params are all valid.
I've tried different Content-Type values, base64 encoding the imageData and several other solutions found in forums and here on SO (most are several years old), but nothing works. The response errorDetail always says Missing file upload.
The issue could be in how the POST request is structured, but I could also be requesting/handling the image data incorrectly. A 2nd (or 3rd, or 4th) set of eyes to check I'm putting this together would be super helpful.
Whew, I have finally solved this.
I was eventually able to get it working thru Postman which provided some hints. Here's the Postman code snippet using request:
var fs = require("fs");
var request = require("request");
var options = { method: 'POST',
url: 'https://api.foursquare.com/v2/photos/add',
qs:
{ checkinId: [MY CHECKING ID],
public: '1',
oauth_token: [MY OAUTH TOKEN],
v: [MY VERSION] },
headers:
{ 'postman-token': '8ce14473-b457-7f1a-eae2-ba384e99b983',
'cache-control': 'no-cache',
'content-type': 'multipart/form-data; boundary=---- WebKitFormBoundary7MA4YWxkTrZu0gW' },
formData:
{ file:
{ value: 'fs.createReadStream("testimage.jpg")',
options: {
filename: 'testimage.jpg',
contentType: null
}
}
}
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The key part of this was fs.createReadStream(). The part I was missing before was to pass the image as a stream to the request.
Using this I was able to figure out the Axios request:
const axios = require("axios");
const querystring = require("qs");
const FormData = require("form-data");
const getImageStream = async function(url) {
return await axios
.get(url, {
responseType: "stream"
})
.then(response => response.data);
};
let form = new FormData();
form.append("file", getImageStream([IMAGE URL]));
const requestURL = "https://api.foursquare.com/v2/photos/add";
const requestParams = {
checkinId: [MY CHECKIN ID],
public: 1,
oauth_token: [MY OAUTH TOKEN],
v: [MY VERSION]
};
const requestConfig = {
headers: form.getHeaders()
};
try {
const postPhoto = await axios.post(
requestURL + "?" + querystring.stringify(requestParams),
form,
requestConfig
);
return postPhoto;
} catch (e) {
console.error(e.response);
}
And voila, the request succeeds and the image is posted to the Foursquare checkin.

Uploading to Cloudinary API - Invalid file parameter

I am working on integrating Cloudinary with my React Native app and am running into a problem when I go to upload using the Cloudinary API. I'm using React Native Image Picker to select an image from the camera roll and using that I get a source uri - example below.
I am getting an error response back from Cloudinary and I'm not sure what it's referring to. "Invalid file parameter. Make sure your file parameter does not include '[]'"
When I use the debugger, I can console log out all the params I am sending in the body of my request. Any suggestions would be much appreciated!
source.uri: /Users/IRL/Library/Developer/CoreSimulator/Devices/817C678B-7028-4C1C-95FF-E6445FDB2474/data/Containers/Data/Application/BF57AD7E-CA2A-460F-8BBD-2DA6846F5136/Documents/A2F21A21-D08C-4D60-B005-67E65A966E62.jpg
async postToCloudinary(source) {
let timestamp = (Date.now() / 1000 | 0).toString();
let api_key = ENV.cloudinary.api;
let api_secret = ENV.cloudinary.api_secret
let cloud = ENV.cloudinary.cloud_name;
let hash_string = 'timestamp=' + timestamp + api_secret
let signature = CryptoJS.SHA1(hash_string).toString();
let upload_url = 'https://api.cloudinary.com/v1_1/' + cloud + '/image/upload'
try {
let response = await fetch(upload_url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
file: {
uri: source.uri,
type: 'image/jpeg'
},
api_key: api_key,
timestamp: timestamp,
signature: signature
})
});
let res = await response.json();
console.log(res);
} catch(error) {
console.log("Error: ", error);
}
}
UPDATE
So I now have base64 encoding working, I think, but I am still getting the same error.
var wordArray = CryptoJS.enc.Utf8.parse(source.uri);
var file = CryptoJS.enc.Base64.stringify(wordArray);
try {
let response = await fetch(upload_url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
file: {
uri: file,
type: 'image/jpeg;base64'
},
api_key: api_key,
timestamp: timestamp,
signature: signature
})
});
So it turns out the source data I was passing in was not formatted correctly. I was able to pass it in from the ImagePicker plugin I was using as an already formatted data URI (the ImagePicker example comes with two ways to capture your source file and I was using the wrong one). I was able to get rid of the CryptoJS stuff and simply pass in file: source.uri
If you are using axios, make sure to include {'X-Requested-With': 'XMLHttpRequest'} in your request headers. eg.
const uploadAgent = axios.create({
baseURL: 'https://api.cloudinary.com',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});

Categories