Uploading images from react with laravel api

Viewed 6229

I'm having trouble uploading files from a react input using a laravel API. I'm working with react-hook-form. My form and onSave are as follows


const onSave = data => {
        // data.picture = imgs; here I tried changing the picture to event.target.files from the file input, didn't work either.
        axios.defaults.headers.common["Authorization"] = "Bearer " + token;
        axios
            .post(`/api/products/store`, data, {})
            .then(res => {
                console.log(res);
            })
            .catch(err => console.log(err));
    };

return (
<form onSubmit={handleSubmit(onSave)} encType="multipart/form-data">
    <input
        type="file"
        name="picture[]"
        label="Product Picture"
        onChange={handlePicInput}
        className={classes.inputFile}
        multiple
        />
//other inputs
</form>
);

my post request leads to this controller method

 public function store(Request $request)
    {
        $imageNames = '';
        $pictures = (object) $request->file('picture');
        //$pictures = $request->allFiles();
        //$pictures = (object) $request->file('picture[]');
        //$pictures = (object) $request->files;
        foreach ($pictures as  $key => $picture) {
            /*WHEN I'M USING POSTMAN OR INSOMNIA, 
             this foreach loop is accessed but 
             the react form just skips the foreach completely */
            $imageNames = $imageNames . $picture->store('product_pictures', 'public') . ',';
        }

        $product = Product::create([
            'name' => $request->name,
            'prices_amountmax' => $request->prices_amountmax,
            'prices_amountmin' => $request->prices_amountmax,
            'brand' => $request->brand,
            'manufacturer' => $request->manufacturer,
            'weight' => $request->weight,
            'category_id' => $request->category_id,
            'stock' => $request->stock,
            'imageurls' => $imageNames
        ]);
        $product->save();
    }

To sum up, I tested uploading images with postman, it works just fine, so the problem must be in the react form? Thank you for any kind of help

2 Answers

To upload images using js you can use FormData. I can't see your handlePicInput method to understand how input change is handled, but may be this snippet can help you to understand what to do further.

function handlePicInput(event){
    let images = event.target.files
    let fd = new FormData()
    fd.append("images", images);
}

Then you can append to fd your other values and send via axios

axios.post(`/api/products/store`, fd)

Again, where to place the code and how to handle other inputs you have to manage by yourself, or provide more data

Try sending it as formData, with multiple files:

const onSave = data => {

  const formData = new FormData();
    for (let i in data) {
      if(i === 'picture[]'){
        for(let file of data[i]){
            formData.append('picture',file);
        }

      }else{
        formData.append(i, data[i])
      }  

    }
  // data.picture = imgs; here I tried changing the picture to event.target.files from the file input, didn't work either.
  axios.defaults.headers.common["Authorization"] = "Bearer " + token;
  axios
      .post(`/api/products/store`, formData, {})
      .then(res => {
          console.log(res);
      })
      .catch(err => console.log(err));
}; 

I tested it with my Node/Express backend and it seems to work. "picture" will be an array of files. If your php backend doesn't recognize this correctly, try changing the formData.append('picture',file) to formData.append('picture[]',file), but then you'll also need to change the name in your php.

Related