Problem sending image after using Expo.ImageManipulator


#1

Hi devs,

I tell you my problem when sending images to a server.

When I use the launchCameraAsync() or launchImageLibraryAsync() methods of ImagePicker and send the selected image via fetch() everything works fine.

Example:

    if (status === 'granted') {
      let image = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ImagePicker.MediaTypeOptions.Image,
        allowsEditing: true,
        quality: 1,
        base64: false,
        exif: false
      }).catch(error => console.log(permissions, {error}));

      if (!image.cancelled) {
        this.sendMessage(method, headers, {
          ...
          image: {uri: image.uri, name: `${Date.now()}`, type: 'image/jpeg'},
          ...
        });
      }
    }
    ...
    _sendMessage = async (method, headers, message) => {
      let body = _serializeToFormData(message);
      let data = {method, headers, body};
      let query = ...;
      ...
      return fetch(query, data);
    }
    _serializeToFormData = (params) => {
      let data = new FormData();
      Object.keys(params).forEach((value, key) => {
        data.append(value, params [value]);
      });
      return data;
    };

But when I manipulate the image by scaling it before sending it to the server using Expo.ImageManipulator, an empty file (0Kb) is sent.

    ...
    _sendMessage = async (method, headers, message) => {
      let imageManipulated = await ImageManipulator.manipulate(
        message.image.uri,
        [{resize: {width: Math.round(width - (width * 20/100))}}],
        {compress: 1, format: 'jpg', base64: false}
      );
      message.image = imageManipulated.uri;
      let body = _serializeToFormData(message);
      let data = {method, headers, body};
      let query = ...;
      ...
      return fetch(query, data);
    }
    ...

If the image of the cache is copied to a directory within the scope of the app, the same problem is reproduced, an empty file (0Kb) is also sent.

    ...
    _sendMessage = async (method, headers, message) => {
      let imageManipulated = await ImageManipulator.manipulate(
        message.image.uri,
        [{resize: {width: Math.round(width - (width * 20/100))}}],
        {compress: 1, format: 'jpg', base64: false}
      );
      let imageTemporal = await FileSystem.copyAsync({
        from: imageManipulated.uri,
        to: `${FileSystem.documentDirectory}tmp/X.jpg`
      });
      message.image = `${FileSystem.documentDirectory}tmp/X.jpg`;
      let body = _serializeToFormData(message);
      let data = {method, headers, body};
      let query = ...;
      ...
      return fetch(query, data);
    }
    ...

Has anyone reproduced this problem? Do I do something wrong? Thank you very much in advance for the help.

Testing on Android with:
Expo: 27.0.0 and 30.0.0
React: 16.3.1
React Native: 0.55.4


#2

The first parameter in ImageManipulator.manipulate needs to be the image URL as far as I know, e.g.,
ImageManipulator.manipulate(message.image.uri, ...)


#4

Hi llamaluvr, yes, you are also right, error when transcribing simplifying the example. I have corrected the example.


#5

Onboard diary…

I have already found the problem. When I manipulate an image recursively or in a loop more than once, it stops working. When I manipulate it only once, it works well.

When viewing through console.log() the paths (file://), sizes and dimensions of the image files generated and sent after manipulating with Expo.ImageManipulator everything seems correct.

Example 1 (do while):

do {
  await Image.getSize(message.image, (width, height) => {
    infoImage = { width: width - Math.round(width*20/100) };
  });
  imageManipulated = await ImageManipulator.manipulate(
    message.image.uri,
    [{ resize: { width: infoImage.width } }],
    { compress: 1, format: 'jpg', base64: false }
  );
  message.image.uri = imageManipulated.uri;
  infoImage = await FileSystem.getInfoAsync(message.image.uri);
}
while (infoImage.size > MAX_UPLOAD_SIZE);

Example 2 (recursivity):

_sendMessage = async (message: {}) => {
    let infoImage = await FileSystem.getInfoAsync(message.image.uri);

    if (infoImage.size > MAX_UPLOAD_SIZE) {
      await Image.getSize(message.image.uri, (width, height) => {
        imageWidth = width - Math.round(width*20/100);
      });
      let imageManipulated = await ImageManipulator.manipulate(
        message.image.uri,
        [{ resize: { width: imageWidth } }],
        { compress: 1, format: 'jpg', base64: false }
      );
      message.image.uri = imageManipulated.uri;
      return this._sendMessage(message);
    }
    this.props.dispatch(sendMessage(message));
});

It’s very strange. Something escapes me.


closed #6

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.