Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReactNativeBlobUtil.fetchBlobForm failed to create request body #98

Closed
afilp opened this issue Jan 11, 2022 · 6 comments
Closed

ReactNativeBlobUtil.fetchBlobForm failed to create request body #98

afilp opened this issue Jan 11, 2022 · 6 comments

Comments

@afilp
Copy link

afilp commented Jan 11, 2022

No matter what I do, I get this Error message in iOS (not in Android, there it works) :

ReactNativeBlobUtil.fetchBlobForm failed to create request body


  • "react-native-blob-util": "^0.13.18"
  • "react-native": "0.66.2",
  • Testing in XCode Simulator, iPhone 13, iOS 15.0
  • Using this for data:
    formData.push({
      name: el.fileName,
      filename: el.fileName,
      type: el.type,
      // Change BASE64 encoded data to a file path with prefix `ReactNativeBlobUtil-file://`.
      // Or simply wrap the file path with ReactNativeBlobUtil.wrap().
      data: ReactNativeBlobUtil.wrap(
        decodeURIComponent(
          Platform.OS === 'ios' ? el.uri.replace('file://', '') : el.uri,
        ),
      ),
    });

I also tried other code, nothing works:
data: ReactNativeBlobUtil.wrap(el.uri)
OR
data: ReactNativeBlobUtil.wrap(decodeURIComponent(el.uri))

Does someone know what else can be done? Thank you.

@afilp
Copy link
Author

afilp commented Jan 11, 2022

UPDATE: The images do not have any problem, the problem is with the video file that the react-native-image-picker is picking. Does this package work with videos in iOS? (Android is OK)

Please see what info the image-picker has for the file:

image

UPDATE 2: I added proper name and filename (not provided by the react-native-image-picker) but still the video causes the error:
image

@afilp
Copy link
Author

afilp commented Jan 12, 2022

For some reason, now it worked, could the problem have been because of the Hot Refresh?

Investigating this and will let you know.

@RonRadtke
Copy link
Owner

In general, yes it could.
Hot refresh is often causing problems and messing with state variables and variables in JS in general. So might be that the data got corrupted due to the refresh.

@afilp
Copy link
Author

afilp commented Jan 14, 2022

@RonRadtke

Thank you Ron, as this also happened to a TestFlight user (who did not have Hot Refresh obviously), I have another theory too:

We are using react-native-image-picker to pick the images.

We store the array of their paths in AsyncStorage so that we are persistent on the next app reload (close/open app, etc.), till we finally post the media files online. This seems to be working.

  1. Maybe an automatic process cleans the files from their respective paths, so the media files are empty when sent.

  2. We are also using code-push. Maybe the reload makes them vanish.

The behavior is not easily replicable though, we cannot make it happen easily.

I mentioned these here, in case they are of help to someone else.

@afilp
Copy link
Author

afilp commented Aug 25, 2022

Hi @RonRadtke This happened again to one of our users. Did something change since Jan 2022 that may have solved this issue?

Thanks!

image

@Streudal
Copy link

Streudal commented Oct 19, 2022

Came across this issue in one of our apps and after some digging this is what solved it for me. Sorry in advance for the verbosity.

NOTE: It was only affecting iOS and not Android but always safe to check both. Also, just for context, we were saving everything under the 'DocumentsDirectoryPath' since it was available on both OS's.

Problem 1 -- ReactNativeBlobUtil.fetchBlobForm request body error

In one of the old forks of this AMAZING library they had the same issue found here. Some comments in there actually solved my problem when trying to use a file as a request body.

// The saved file uri in our local db. (iOS)
const fileUri =  '/Users/tylerstreu/Library/Developer/CoreSimulator/Devices/2EFD9303-F7A7-4AA4-B425-659C26A2859F/data/Containers/Data/Application/1855B58F-E065-4AA7-BCB9-90C2342E0807/Documents/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg';

// Might look something like this on Android: /data/user/0/com.<app_package_name>/files/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg

// Old code
const data = RNFetchBlob.wrap(fileUri); 
// would return something like 'RNFetchBlob-file:///Users/<your_username>/Library/Developer/CoreSimulator/Devices/2EFD9303-F7A7-4AA4-B425-659C26A2859F/data/Containers/Data/Application/1855B58F-E065-4AA7-BCB9-90C2342E0807/Documents/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg'

// New code
const data = RNFetchBlob.wrap(fileUri).replace('file://', '');
// to get it to this format:  'RNFetchBlob-/Users/<your_username>/Library/Developer/CoreSimulator/Devices/2EFD9303-F7A7-4AA4-B425-659C26A2859F/data/Containers/Data/Application/1855B58F-E065-4AA7-BCB9-90C2342E0807/Documents/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg'
// removed the 'file://' part of the string

// Then I was able to do something like this no problem
const response = await RNFetchBlob.fetch(
  'POST', 
  <some_url>,
  {
    'Content-Type': 'multipart/form-data',
  },
  data,
);

Problem 1 solved!

Alternate Solution to Problem 1

*** If this is consistent then it would mean that it's not a problem with the library but problems with dealing with the intricacies of each OS and pathing ***

Sometimes trying to parse out that file:// didn't work and the error still persisted. Another thing I noticed was that if this happened, just re-generating the file uri from scratch resolved the issue without having to remove the file:// part of the string in iOS. Both iOS and Android still working with the file:// in the string after using wrap. For example,

// The saved file uri in our local db. (iOS)
const fileUri =  '/Users/tylerstreu/Library/Developer/CoreSimulator/Devices/2EFD9303-F7A7-4AA4-B425-659C26A2859F/data/Containers/Data/Application/1855B58F-E065-4AA7-BCB9-90C2342E0807/Documents/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg';

// Might look something like this on Android: /data/user/0/com.<app_package_name>/files/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg

// Re-generate uri to file. Basically ignoring the saved fileUri above.
const actualFileUri = `${RNFetchBlob.fs.dirs.DocumentsDir}/<rest of path to image file>`;
const data = RNFetchBlob.wrap(actualFileUri);
// to get it to the expected format when using straight up `wrap`:  'RNFetchBlob-file:///Users/<your_username>/Library/Developer/CoreSimulator/Devices/2EFD9303-F7A7-4AA4-B425-659C26A2859F/data/Containers/Data/Application/1855B58F-E065-4AA7-BCB9-90C2342E0807/Documents/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg'

// Then I was able to do something like this no problem
const response = await RNFetchBlob.fetch(
  'POST', 
  <some_url>,
  {
    'Content-Type': 'multipart/form-data',
  },
  data,
);

Problem 1 solved -- again!

Problem 2 -- Images go blank on app update

Now this may not be the best place to put this but just in case someone goes down the same rabbit hole -- here it is!

A little background, we had an app published, we released new updates yada yada yada, and then noticed the images being saved from our form data are no longer viewable on iOS (but only after app updates which can replicated by just rebuilding the app if you are testing on an emulator and need to reproduce this). The images went blank but it still new that something was there, giving us hope that it wasn't actually 'corrupted.'

In the README of this library I found this note on readFile that led me to believe this is part of the issue of our current implementation.

We were saving the the absolute path to the local db and just using that stored string, the image uri, to display the image. Sounds straight forward and easy but for some reason on iOS it doesn't behave as you would expect, as mentioned in the 'readFile' url above it states:

On iOS platform the directory path will be changed every time you access to the file system...

In conclusion, this is what I had to change in order for images to not get 'corrupted' (images go blank/black/etc) on my application.

** Keeping in mind that it wasn't effecting Android and was only needed for iOS but most likely can be used for both OS's. **

import { Image } from 'react-native';

interface Photo {
  uri: string;
// other props that aren't necessary for this example
}

function ImageViewer ({photo}: {photo: Photo}) {
// Old code
  const sourceUri= Platform.OS === 'android' ? `file://${photo.uri}` : photo.uri;

// New code -- Notice this preserves some of the old format just because Android was working so why change it... at least for now.
  const sourceUri = `${Platform.OS === 'android' ? 'file://' : ''}${RNFetchBlob.fs.dirs.DocumentDir}/<app_name>/${photo.uri.substring(photo.uri.indexOf('/Images/') + 1)}`;
// The sourceUri should look like this for each OS:
// iOS: '/Users/tylerstreu/Library/Developer/CoreSimulator/Devices/2EFD9303-F7A7-4AA4-B425-659C26A2859F/data/Containers/Data/Application/1855B58F-E065-4AA7-BCB9-90C2342E0807/Documents/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg';
// Android: '/data/user/0/com.<app_package_name>/files/<app_name>/Images/<some_nested_folder>/<image_filename>.jpg'

  return (
    <Image
      style={{ width: 400, height: 380 }}
      resizeMethod="resize"
      source={{ uri: sourceUri }}
     />
  );
}

The new sourceUri created for iOS fixed my issue and now Problem 2 is solved!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants