Search code examples
reactjslaravelform-data

Uploading image with ReactJS FormData and Laravel API


I am having trouble uploading an image from a React input using a Laravel API. This is a profile page that allows the user to edit his profile, the logged in user id is retrieved when the page loads. When the user chooses an image it will call the API put method to update the user's profile, to store the image in the database in the profile_picture column and to store the image in Laravel's storage > app > public in a folder called profilePictures so I can retrieve and display the images when stored on the FrontEnd. This is the profile page:

import React, { useEffect, useState } from "react";
import axiosClient from "../axios-client";

export const Profile = () => {
  const [user, setUser] = useState({});
  let profilePicture = null;

  const editProfile = () => {
    const headers = {
      headers: { "Content-Type": "multipart/form-data" },
    };
    const formData = new FormData();
    formData.append("profile_picture", profilePicture);
    axiosClient
      .put(`/profile/${user.id}`, formData, headers)
      .then(() => {
        console.log("success");
      })
      .catch((err) => {
        console.log(err);
      });
  };

  useEffect(() => {
    axiosClient.get("/user").then(({ data }) => {
      setUser(data);
    });
  }, []);

  return (
    <>
      <div className="profile">
        <h2>Profile Info</h2>

        <input
          type="file"
          name="profile_picture"
          onChange={(e) => {
            profilePicture = e.target.files[0];
            editProfile();
          }}
        />
      </div>
    </>
  );
};

My put request leads to this controller method:

<?php

namespace App\Http\Controllers\Api;

use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\EditProfileRequest;
use Illuminate\Support\Facades\Storage;

class UserController extends Controller
{
    // edit profile
    public function editProfile(EditProfileRequest $request, User $id){
        $payload = $request->validated();
        $storage = Storage::disk('public');

        if($request->hasFile('profile_picture')){
            $file = $request->file('profile_picture');
            $extension = $file->getClientOriginalExtension();
            $filename = time() .'.'.$extension;
            $storage->put($filename, file_get_contents($request->file('profile_picture')));
            $payload['profile_picture']= 'uploads/profilePictures/'.$filename;
        }

        $id->update($payload);
    }
}

users table:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('role')->nullable();
            $table->integer('times_donated')->nullable();
            $table->string('email')->unique();
            $table->longText('description')->nullable();
            $table->string('profile_picture')->nullable();
            $table->string('background_picture')->nullable();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

EditProfileRequest Rules:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class EditProfileRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array|string>
     */
    public function rules(): array
    {
        return [
            'profile_picture' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
        ];
    }
}

API Route:

Route::put('/profile/{id}', [UserController::class, 'editProfile']);

I tried multiple solutions but couldn't make it work. When I upload an image or a file it is not getting validated or stored and I'm getting a success in the console even though it is not working. I am sorry if I made something unclear as I'm still a beginner and thank you in advance for the help :)


Solution

  • This is a problem with PHP itself, uploading files using the PUT method does not work correctly, just use POST

    How to use PUT method in Laravel API with File Upload