0

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

1
  • show me your payload log Commented Nov 3, 2023 at 9:05

2 Answers 2

0

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');
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I already tried appending a similar object to the formData "image" field, but then I get this error for the .append() method: ```Argument of type '{ name: any; size: any; type: any; uri: any; }' is not assignable to parameter of type 'string | Blob'.´´´
check my answer is edited now
If you still have any problems let me know
0

I am working on a React Native app using Expo, where I want to capture an image with the camera, send it to my server as part of a POST request, and handle it using multer on the backend (Node.js / Express).

I encountered an issue with the following code:

const img = await fetch(imageUri);
const blob = await img.blob();

This code executes without throwing any error but also doesn’t produce any usable result.

Here’s my solution:

Client (Expo / React Native):

import { CameraView } from "expo-camera";
// ...
const cameraRef = useRef<CameraView>(null);
// ..
const picture = await cameraRef.current.takePictureAsync();
const product = await saveProduct("name of the product", picture.uri);
// ...

export async function saveProduct(
  name: string,
  imageUri: string
): Promise<ProductInfo> {
  const image = JSON.parse(JSON.stringify({ name, uri: imageUri }));
  const formData = new FormData();
  formData.append("name", name);
  formData.append("image", image);
  const url = `${API_URL}/products`;
  const response = await fetch(url, { method: "POST", body: formData });
  return response.json();
}

Server (Node.js + Express):

import express from "express";
import multer from "multer";
// ...

const upload = multer({
  limits: { fileSize: 50 * 1024 * 1024 },
  dest: "uploads/",
});

const app = express();

app.post("/api/products", upload.single("image"), (req, res) => {
  console.debug("Received file", req.file);
  console.debug("Received file.originalname", req.file.originalname);
  console.debug("Received extra form data - name", req.body.name);
  res.json({ success: true });
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.