10

I am setting headers and body , Using fetch with Post to upload image on server.I am getting the response code 200 but it is not uploading image but rest of the Data is getting uploaded.

Here is the code of body:

export default function setRequestBody(imagePath){

    let boundry = "----WebKitFormBoundaryIOASRrUAgzuadr8l";

    let body = new FormData();

    body.append("--"+boundry+"\r\n");
    body.append("Content-Disposition: form-data; name=imageCaption\r\n\r\n");
    body.append("Caption"+"\r\n");
    body.append("--"+boundry+"\r\n");
    body.append("Content-Disposition: form-data; name=imageFormKey; filename =iimageName.pngg \r\n");
    body.append("Content-Type: image/png \r\n\r\n");
    body.append({uri : imagePath});
    // appened image Data Here
    body.append("\r\n");
    body.append("--"+boundry+"--\r\n");
    return body

}

Please help.What mistake I am making. :(

1

5 Answers 5

20

I've found the solution:

let body = new FormData();
body.append('photo', {uri: imagePath,name: 'photo.png',filename :'imageName.png',type: 'image/png'});
body.append('Content-Type', 'image/png');

fetch(Url,{ method: 'POST',headers:{  
     "Content-Type": "multipart/form-data",
     "otherHeader": "foo",
     } , body :body} )
  .then((res) => checkStatus(res))
  .then((res) => res.json())
  .then((res) => { console.log("response" +JSON.stringify(res)); })
  .catch((e) => console.log(e))
  .done()

** filename is optional...

Sign up to request clarification or add additional context in comments.

6 Comments

it gives me error of TypeError: Network request failed any solution?
I believe body.append('Content-Type', 'image/png'); is unnecessary.
@Rajeev wtf is checkStatus?
Want to know how did your imagePath look like, was it 'https://...' or was it like require('../sample.jpeg)? Cause I am facing the same problem.
Argument of type '{ uri: string; name: string; filename: string; type: string; }' is not assignable to parameter of type 'string | Blob'.
|
8

The problem is body.append({uri : imagePath}); because react native JSC does not support File and Blob, so you have to use libraries.

react-native-fetch-blob has very good support for this, example from its README.md

    RNFetchBlob.fetch('POST', 'http://www.example.com/upload-form', {
        Authorization : "Bearer access-token",
        otherHeader : "foo",
        'Content-Type' : 'multipart/form-data',
    }, [
    // element with property `filename` will be transformed into `file` in form data
    { name : 'avatar', filename : 'avatar.png', data: binaryDataInBase64},
    // custom content type
    { name : 'avatar-png', filename : 'avatar-png.png', type:'image/png', data: binaryDataInBase64},
    // part file from storage
    { name : 'avatar-foo', filename : 'avatar-foo.png', type:'image/foo', data: RNFetchBlob.wrap(path_to_a_file)},
    // elements without property `filename` will be sent as plain text
    { name : 'name', data : 'user'},
    { name : 'info', data : JSON.stringify({
      mail : '[email protected]',
      tel : '12345678'
    })},
  ]).then((resp) => {
    // ...
  }).catch((err) => {
    // ...
  })

3 Comments

Using this gives error : Undefined is an object (evaluating RNFetchBlob.DocumentDir)
this is a native module, you'll have to link native libraries and recompile the project.
This actually still works in 2023! I spend 8 hours on formData not working on React Native for Android. Thank you!
0

Building upon @Ven Jest's answer, if you want to upload multiple images I've made a minimal working example:

App.js

import { useState } from "react";
import { Button, Image, ScrollView, View } from "react-native";
import { launchImageLibrary } from 'react-native-image-picker';
import RNFetchBlob from "rn-fetch-blob";


async function add_images(setImages) {

  const images = await launchImageLibrary({ mediaType: 'photo', selectionLimit: 0 });

  if (images.didCancel)
    return

  setImages(val => {
    let copy_val = [...val]

    images.assets.forEach((item) => {
      copy_val.push({ uri: item.uri, filename: item.fileName })
    })

    return copy_val
  });

}

async function upload_images(images) {

  let data = []
  images.forEach((item, index) => {
    data.push({ name: 'images_data', filename: item.filename, data: RNFetchBlob.wrap(item.uri) })
  })

  // you may have to use another route instead of localhost
  RNFetchBlob.fetch('POST', 'localhost:3000/upload_images', { 'Content-Type': 'multipart/form-data' }, data);
}

export default function App() {

  const [images, setImages] = useState([]) // array of URIs
  
  return (<>

    <View style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginVertical: 50 }}>
      <Button title="Add Images" onPress={() => { add_images(setImages) }} />
      <Button title="Clear Images" onPress={() => { setImages([]) }} />
      <Button title="Upload Images" onPress={() => { upload_images(images) }} />
    </View>

    <ScrollView horizontal={true}>
      {
        images.map((item, index) => {
          return (<Image key={index} style={{ height: 400, width: 400 }} source={{ uri: item.uri }} />)
        })
      }
    </ScrollView>

  </>)
}

Node.js

// import fs from 'fs';
import multer from "multer";
import express from 'express';
const server = express();

var upload = multer({ dest: 'uploads/' });

server.post('/upload_images', upload.array('images_data'), (req, res) => {
    console.log(req.files);
    
    // req.files.forEach(item => {
    //     fs.renameSync(item.path, item.destination + item.originalname)
    // })
});

const PORT = 3000
server.listen(PORT, () => {
    console.log(`listening at ${PORT} ...`);
});

For reference, the server console.log is as such:

[
  {
    fieldname: 'images_data',
    originalname: 'image_1.jpg',
    encoding: '7bit',
    mimetype: 'application/octet-stream',
    destination: 'uploads/',
    filename: '8466672ac610519ce55f23af6926c9f',
    path: 'uploads/8466672ac610519ce55f23af6926c9f',
    size: 86475
  },
  {
    fieldname: 'images_data',
    originalname: 'image_2.jpg',
    encoding: '7bit',
    mimetype: 'application/octet-stream',
    destination: 'uploads/',
    filename: 'd8bf4a571ef544542e98aa3aeddbdeb2',
    path: 'uploads/d8bf4a571ef544542e98aa3aeddbdeb2',
    size: 79512
  },
  {
    fieldname: 'images_data',
    originalname: 'image_3.jpg',
    encoding: '7bit',
    mimetype: 'application/octet-stream',
    destination: 'uploads/',
    filename: '04bf7f37791a20023bca5e4d90e2e7b67',
    path: 'uploads/04bf7f37791a20023bca5e4d90e2e7b67',
    size: 2271
  }
]

I was stuck on this for quite a while, hope this helps :)

Comments

-1

I've found the solution to Upload the Image on server in React Native:

const formdata = new FormData();
formdata.append('image[]', {
          name: 'test.' + imageurl?.type?.substr(6),
          type: imageurl?.type,
          uri:
            Platform.OS !== 'android'
              ? 'file://' + imageurl?.uri
              : imageurl?.uri,
        });
const res = await axios.post(url, formdata, {
        headers: {
          Accept: '*/*',
          'Content-type': 'multipart/form-data',
        },
      });

1 Comment

Where is append coming from in JS?
-1

//First Install and import Image-piker //install

npm i react-native-image-picker

//import

import * as ImagePicker from 'expo-image-picker';

//then

const [image, setImage] = React.useState(null);
const [Type,setType]=React.useState('')

//Get the image

const pickImage = async () => {
  let result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.All,
    allowsEditing: true,
    aspect: [4, 3],
    quality: 1,
  });

  console.log(result);

  if (!result.cancelled) {
      // extract the filetype
   setType(result.uri.substring(result.uri.lastIndexOf(".") + 1));
 setImage(result.uri);
 
  }
};

//show image return

<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button title="Ecolher Foto" onPress={pickImage} />
      {image && <Image source={{ uri: image }} style={{ width: 150, height: 150 }} />}
    </View>

//UpLoad Image

var validatinoApi ='https://seusite.com/OOP/';
var headers={
 'Accept':'application/json',
 "Content-Type": "multipart/form-data",
 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
 'Access-Control-Allow-Origin':'*',
 'crossDomain': 'true',
 'Host': 'https://seusite.com/OOP/',
 'Origin': 'https://origem.com',
 
  };
 /*'crossDomain': 'true',*/
 var Data={
  image:image,
  namefoto: `photo.${namefoto}`,
  type: `image/${Type}`

 };

 fetch(validatinoApi,
  {
   method:'POST',
   headers:headers,
   body:JSON.stringify(Data)
 }).then((response)=>response.json())
   .then((response)=>{
     if(response.statusCode==200){
//Do something
}

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.