12

I just learning react and I create an gallery App, but I have problem with posting picture to API. The problem is that when I click on button ADD there's nothing happend just in console.log I get an error 500.

Here is my component with post request:

class AddPhoto extends Component {
constructor(props) {
    super(props);
    this.state = {
        modal: false,
        images: [],
        isLoading: false,
        error: null,
    };

    this.toggle = this.toggle.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
}

toggle() {
    this.setState({
        modal: !this.state.modal
    });
}

handleClick(event) {
    event.preventDefault();
    this.setState({
        modal: !this.state.modal
    });
}

handleSubmit(event){
    event.preventDefault();

    this.setState({ isLoading: true });
    let path = this.props.path;

    fetch(`http://.../gallery/${path}`, {
        method: 'POST',
        headers: {'Content-Type':'multipart/form-data'},
        body: new FormData(document.getElementById('addPhoto'))
    })
        .then((response) => response.json())
        .then((data)=>{
            this.setState({images: data.images, isLoading: false});
            this.props.updateImages(data.images);
        })
        .catch(error => this.setState({ error, isLoading: false}));
}

render() {
    return (
        <Card className="add">
            <div className="link" onClick={this.toggle}>
                <CardBody>
                    <CardTitle>Add picture</CardTitle>
                </CardBody>
            </div>
            <Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
                <div className="modal-header">
                    ...
                </div>
                <ModalBody>
                    <form className="addPhotoForm" id="addPhoto" onSubmit={this.handleSubmit}>
                        <input type="file" required />
                        <Button color="success" type="Submit">Add</Button>
                    </form>
                </ModalBody>
            </Modal>
        </Card>
    );
}
}

Do you have any idea what am I doing wrong, why is not working, why I get error 500?

Thanks for helping me.

Zoltan Kovacs
  • 131
  • 1
  • 2
  • 7
  • The error is much more informative than just a code number - what does it say? – Idan Beker Jan 16 '18 at 15:00
  • POST http://api.../gallery/test2 500 (Internal Server Error) – Zoltan Kovacs Jan 16 '18 at 15:04
  • My idea is that the file was not attached correctly, but there is no need for a guessing game. Go to developer console under the network tab and check what exactly the server is screaming about. – Idan Beker Jan 16 '18 at 15:14
  • code: **500** description: **"Internal Server Error"** exception: **"ValueError("Invalid boundary in multipart form: ''",)"** name: **"INTERNAL_SERVER_ERROR"** – Zoltan Kovacs Jan 16 '18 at 15:46
  • Ok so I was right, the server expected a different format (It varies in each framework). What worked for me in lavarel is to do body: new FormData(document.getElementById('addPhoto').files[0]) – Idan Beker Jan 16 '18 at 16:15
  • that's not work for me. When I modify it as you written, I get error: **Cannot read property '0' of undefined** – Zoltan Kovacs Jan 16 '18 at 22:49

4 Answers4

29

according to this https://muffinman.io/uploading-files-using-fetch-multipart-form-data it works in different way, at least for me it works as well.

const fileInput = document.querySelector('#your-file-input') ;
const formData = new FormData();

formData.append('file', fileInput.files[0]);

    const options = {
      method: 'POST',
      body: formData,
      // If you add this, upload won't work
      // headers: {
      //   'Content-Type': 'multipart/form-data',
      // }
    };
    
    fetch('your-upload-url', options);

You should remove the 'Content-Type': 'multipart/form-data' and it started to work.

Ruslan Korkin
  • 3,973
  • 1
  • 27
  • 23
3

This is part of my upload component. Look how i do it, you can modify it, with upload button, if you need.

addFile(event) {
    var formData = new FormData();
    formData.append("file", event.target.files[0]);
    formData.append('name', 'some value user types');
    formData.append('description', 'some value user types');
    console.log(event.target.files[0]);

    fetch(`http://.../gallery/${path}`, {
        method: 'POST',
        headers: {'Content-Type': 'multipart/form-data'},
        body: {event.target.files[0]}
    })
    .then((response) => response.json())
    .then((data) => {
        this.setState({images: data.images, isLoading: false});
        this.props.updateImages(data.images);
    })
    .catch(error => this.setState({error, isLoading: false}));
}


render() {
    return (
        <div>
            <form encType="multipart/form-data" action="">
                <input id="id-for-upload-file" onChange={this.addFile.bind(this)} type="file"/>
            </form>
        </div>)
}
Nicolás Alarcón Rapela
  • 2,714
  • 1
  • 18
  • 29
egorchik
  • 531
  • 1
  • 4
  • 12
1

This worked fine for me, just try it:

var myHeaders = new Headers();
myHeaders.append("Accept", "application/json");
myHeaders.append("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJh");

var formdata = new FormData();    
formdata.append("image", fileInput.files[0], "Your_iamge_URL");

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: formdata,
  redirect: 'follow'
};

fetch("YOUR_API_ToCall", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));
Cosmin
  • 2,354
  • 2
  • 22
  • 39
1

If you need to send a request with more attributes than the image use:

document.getElementById('inputPhoto').addEventListener('change', (e) => {  
  let data = new FormData();
  const image = e.target.files[0];
  data.append('id', 'sendIDHere');
  data.append('name', 'sendNameHere');
  data.append('image', image);

  fetch('/apiToReceiveImage', {
    method: 'POST',    
    body: data
  }).then(async (_res) => {
    const result = await _res.json();
    console.log(result);
  });
});

Remember that all attributes should be appended BEFORE the image

Nico Serrano
  • 577
  • 4
  • 14