Getting Internal Server Error when sending POST request with an image file to database using React JS and Laravel

Viewed 608

I'm trying to upload an image using React JS and REST API with Laravel as backend.

I have a Partner model that has a name and a logo. I created a form to enter its name and logo.

When I enter just the name of the partner and submit, I find the new partner added to the database.

But when I try to upload the partner's logo I get this error: POST http://localhost:8000/api/eventpartners 500 (Internal Server Error)

And on my browser, when I go to inspect->Network I find this error: {message: "Array to string conversion", exception: "ErrorException",…}

Here is the AddPartnerForm.js code:

import React, { Component } from 'react';
import Box from '@material-ui/core/Box';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Skeleton from '@material-ui/lab/Skeleton';
import axios, { post } from 'axios';



export default class AddPartnerForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      newPartnerData: {
        partnerlogoimage: '',
        partnername: ''
      },
      partnerlogouploaded: false
    }
    this.onFormSubmit = this.onFormSubmit.bind(this)
    this.onChange = this.onChange.bind(this)
    this.addPartner = this.addPartner.bind(this)
    this.onUpload = this.onUpload.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
  }


  onChange(e) {
    this.setState({
      newPartnerData: {
        [e.target.name]: e.target.value
      }
    });
  }

  onUpload(e) {
    let file = e.target.files[0];
    this.setState(prev => ({
      ...prev,
      newPartnerData: {
        ...prev.newPartnerData,
        partnerlogoimage: file,
      },
      partnerlogouploaded: true
    }));
  }

  handleSubmit(e) {
    e.preventDefault()
    this.addPartner();
    console.log(this.state.newPartnerData)
  }

  addPartner() {
    const url = 'http://localhost:8000/api/eventpartners';
    return axios.post(url, this.state.newPartnerData)
      .then((response) => {
        let { partners } = this.state;
        partners.push(response.data);
        this.setState({
          newPartnerData: {
            partnerlogoimage: '',
            partnername: '',
          }
        })
      })
  }


  render() {
    const newPartnerData = this.state.newPartnerData;
    const partnerlogouploaded = this.state.partnerlogouploaded;
    let partnerlogo;
    if (partnerlogouploaded) {
      partnerlogo = <img style={{ width: 200, height: 200 }} src={this.state.partnerlogoimage} />;
    } else {
      partnerlogo = <Skeleton variant="rect" width={200} height={200} />;
    }
    return (
      <form >
        <TextField
          name="partnername"
          autoFocus
          margin="dense"
          id="name"
          label="Partner's name"
          type="text"
          fullWidth
          onChange={this.onChange}
        />
        <input accept="image/*"
          style={{ display: 'none' }}
          id="contained-button-partner-logo"
          name="partnerlogoimage"
          multiple
          type="file"
          diplay="none"
          onChange={this.onUpload} />
        <label htmlFor="contained-button-partner-logo" className="upload-button">
          <Button variant="contained" color="primary" component="span" >
            Upload Partner Logo
        </Button>
        </label>
        <Box width={200} height={200} marginRight={0.5} my={5}>
          {partnerlogo}
        </Box>
        <Button type="submit" onClick={this.handleSubmit} variant="contained" color="primary" component="span" >
          Add
        </Button>
      </form>
    )
  }
}

I'm using Laravel as the backend of this app.

This is the EventPartnerController.php file if it helps:

<?php

namespace App\Http\Controllers;

use App\Eventpartner;
use Illuminate\Http\Request;

class EventpartnerController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $eventpartners = Eventpartner::all();
        return $eventpartners;
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->all();
        $eventpartner = new Eventpartner();
        $eventpartner->event_id = $request->event_id;
        $eventpartner->partnername = $request->partnername;
        $eventpartner->partnerlogoimage = $request->partnerlogoimage;
        $eventpartner -> save();
        return response()->json($eventpartner);
    }

    
}

And this is the routing file api.php :

<?php
Use App\Eventpartner;
Use App\Http\Controllers\EventpartnerController;

Route::get('eventpartners', function() {
    return Eventpartner::all();
});
Route::post('eventpartners', 'EventpartnerController@store');

If there's any missing code that I should add to this question please tell me in the comments.

1 Answers

You are sending partnerLogoImage in a string type but images should always be send in Blob type to the backend. I think your backend is fine but the problem is on Frontend side where you are not using Blob type for image (partnerLogoImage). Please send the image in Blob type in the axios POST request and it will work fine.

Related