Search code examples
react-nativefile-uploadexpofetch-api

Blob/File is empty when sending it using fetch


I use expo-camera in my react native app to take images, which returns the images location as a string. I then take this string and try to upload it to a laravel php backend:

const uploadImage = async (
    imageUri: string,
    protocolId: number,
    name: string
  ) => {

    const img = await fetch(imageUri);
    const blob = await img.blob();
    const file = new File([blob], imageUri);

    const formData = new FormData();
    formData.append("image", file);
    formData.append("protocolId", protocolId.toString());
    formData.append("name", name);

    fetch(POST_UPLOAD_PROTOCOL_PHOTO, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${user?.token}`,
      },
      body: formData,
    })

I tested everything on an Iphone. My backend received the values for protocolId and name, but the image field always gets sent as an empty file. I tried intercepting the api call using the networking debugger and indeed it seems that the file is empty, since the content-length of the request is way to small for an image.

I tried removing "file://" from the image uri, but that did not help. I tried the api call using Postman and added a file using form-data and that worked perfectly fine. I tried solutions as described in other stackoverflow posts like this one (Uploading blob/file in react-native, contents is empty), but I get an error for this

formData.append("img", {
    uri,
    name: `photo.${fileType}`,
    type: `image/${fileType}`,
  });

since formData.append() only takes string or Blob


Solution

  • Try with my function

    What changes have I made to this function, I changed the payload for the image (direct URL will not work) and Content-Type 'multipart/form-data' in the headers ( without Content-Type form data API will not work)

    const uploadImage = async (
        imageUri: string,
        protocolId: number,
        name: string
    ) => {
    
        const formData = new FormData();
        formData.append('name', name);
        formData.append('protocolId', protocolId.toString());
        formData.append('image',
            JSON.parse(JSON.stringify({
                name: imageUri?.fileName,  //file name here
                size: imageUri?.fileSize,  // optional
                type: imageUri?.type,   // file type here
                uri: imageUri?.uri  // file url here
            })))
    
        let res = await fetch(
            `${baseUrl}/fame/saveImage`,
            {
                method: 'post',
                body: formData,
                headers: {
                    Authorization: `Bearer ${user?.token}`,
                    'Content-Type': 'multipart/form-data',
                },
            }
        );
        let responseJson = await res.json();
        if (responseJson.status == 1) {
            alert('Upload Successful');
        }
    }