Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 435
merry-go-round Avatar asked Oct 26 '17 10:10

merry-go-round


2 Answers

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(); 
}
like image 152
sebastianf182 Avatar answered Sep 28 '22 08:09

sebastianf182


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.

like image 33
linasmnew Avatar answered Sep 28 '22 07:09

linasmnew