Skip to content

Instantly share code, notes, and snippets.

@atomjoy
Last active March 12, 2025 08:26
Show Gist options
  • Save atomjoy/78e701d57070afe84596b1e51249b135 to your computer and use it in GitHub Desktop.
Save atomjoy/78e701d57070afe84596b1e51249b135 to your computer and use it in GitHub Desktop.
How to upload avatar using fetch function in JavaScript with Laravel.

Fetch API JavaScript

Upload avatar

Image upload form in html

<img src="/default/avatar.webp" alt="Avatar image" id="avatar">

<form method="post" enctype="multipart/form-data" onsubmit="getData(event)">
    <input type="file" name="avatar" accepts="image/*" id="input">
    <input type="submit" value="Submit">
</form>

Get the URL of an image selected in a form

// Form file input event
document.querySelector('#input').onchange = e => {
    // Form input file on disk
    const file = e.target.files[0];
    // File url
    const url = URL.createObjectURL(file); 
    // Page img element
    document.querySelector('#avatar').src = url; 
};

Laravel upload avatar with csrf_token in form

async function getData(e) {
    e.preventDefault()
    
    let response;

    try {
        const formData = new FormData(e.target)
        // const formObj = Object.fromEntries(formData);
        // const entries = [...formData.entries()];
        // const values = [...formData.values()];

        formData.append('_token', '{{ csrf_token() }}')

        response = await fetch('/web/api/avatar/upload', {
            method: 'POST',
            body: formData,
        });

        if (!response.ok) {
            const json = await response.json();
            console.log(json);
            throw new Error('Response status: ' + response.status);
        }

        const json = await response.json();
        console.log(json);
    } catch (error) {
        console.error(error.message);
    }
}

Laravel upload avatar with csrf_token in headers

async function getData(e) {
    e.preventDefault()

    let response;

    try {
        const formData = new FormData(e.target)

        response = await fetch('/web/api/avatar/upload', {
            method: 'POST',
            // Upload image and form data
            body: formData,
            headers: {
                'Accept': 'application/json',
                'X-CSRF-TOKEN': '{{ csrf_token() }}'
            },
            // Send json data
            // body: JSON.stringify({ username: 'example', email: 'email@example.org' }),
            // headers: {
            //     'Accept': 'application/json',
            //     'Content-Type': 'application/json',
            //     'X-CSRF-TOKEN': '{{ csrf_token() }}'
            // }
        });

        if (!response.ok) {
            const json = await response.json();
            console.log(json);
            throw new Error('Response status: ' + response.status);
        }

        const json = await response.json();
        console.log(json);
    } catch (error) {
        console.error(error.message);
    }
}

Laravel save uploaded avatar to file

<? php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class UserController extends Controller {

    public function uploadAvatar(Request $request) 
    {
        // Logged user id
        // $id = Auth::id() ?? 0;
        
        // For single error use bail
        $request->validate([
           'avatar' => 'bail|required|image|mimes:png|max:2048|dimensions:max_width=256,max_height=256',
        ]);

        $valid = $request->validated();

        $extension = $request->file('avatar')->extension();       
        
        $path = Storage::putFileAs('avatars', $request->file('avatar'), 'avatar-' . $request->user()->id . '.png');

        $url = Storage:: url($path);

        return response() -> json([
            'image' => $path,
            'url' => $url,
        ]);
    }
} 

Laravel resize and save to disk uploaded image

Install first: composer require intervention/image

<?php

use Intervention\Image\ImageManager;

$image = ImageManager::gd()->read($request->file('avatar'))->resize(
    config('default.avatar_resize_pixels', 256),
    config('default.avatar_resize_pixels', 256)
)->toWebp();

$path = Storage::put('avatars/aratar.webp', (string) $image);
$path = Storage::putFileAs('avatars', (string) $image, 'avatar.webp');

// Get image url https:// or public path, get image with <img src="" onerror="this.onerror=null; fetchImageUrl(this)">
$url = Storage::url($path);

// Return image response
return Storage::response($path);

Laravel read image and get blob url

Install first: composer require intervention/image

<?php

use Intervention\Image\ImageManager;
use Intervention\Image\Drivers\Gd\Driver;

$image = (new ImageManager(new Driver()))->read('images/example.gif');

// Save to disk
$path = Storage::put('avatars/aratar.gif', (string) $image);
$path = Storage::putFileAs('avatars', (string) $image, 'avatar.gif');

// Get image url https:// or public path, get image with <img src="" onerror="this.onerror=null; fetchImageUrl(this)">
$url = Storage::url($path);

// Base64 image
$data_uri = $image->toGif()->toDataUri();

// Return image response
return Storage::response($path);

Image response

<?php
$default = 'dir/image.webp';

if (!file_exists($default)) {
    $default = fake()->image(
        null,
        128,
        128,
        null,
        true,
        true,
        'avatar',
        true,
        'png'
    );
}

return response(file_get_contents($default))->header('Content-Type', 'image/png');

Laravel show or download image from storage

<?php

namespace App\Http\Controllers;

use App\Http\Requests\BaseRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class UserController extends Controller {
    /**
     * Show form
     *
     * @param Request $request
     * @return void
     */
    public function index(Request $request) {
        return view("upload");
    }

    /**
     * Upload avatar
     *
     * @param Request $request
     * @return Illuminate\Http\Response
     */
    public function uploadAvatar(Request $request) {
        $request->headers->set('Accept', 'application/json');

        $request->validate([
            // For dingle error use bail
            'avatar' => 'bail|required|image|mimes:png|max:2048|dimensions:max_width=256,max_height=256',
        ]);

        $extension = $request->file('avatar')->extension();
        // $path = Storage::putFileAs('avatars', $request->file('avatar'), 'avatar-' . $request->user()->id . '.png');
        $path = Storage::putFileAs('avatars', $request->file('avatar'), 'avatar-1.png');
        $url = Storage::url($path);

        return response()->json([
            'image' => $path,
            'url' => $url,
        ]);
    }

    /**
     * Get avatar image
     *
     * @param [int] $id
     * @return Illuminate\Http\Response
     */
    public function getAvatarImage($id) {
        // $user = User::where('id', $id)->first();
        // $avatar = $user->avatar;

        $avatar = 'avatars/avatar-' . (int) $id . '.png';
        $mime = Storage::mimeType($avatar); // 'image/png'

        if (Storage::exists($avatar)) {
            $headers = [
                'Content-Type' => $mime,
            ];

            // Downloading image content from aws s3 and displaying it from the server is idiotic
            return response(Storage::get($avatar), 200, $headers);
        }

        return response()->file(public_path('default/avatar.png'));
    }

    /**
     * Download avatar image
     *
     * @param [int] $id
     * @return Illuminate\Http\Response
     */
    public function downloadAvatarImage($id) {
        $avatar = 'avatars/avatar-' . (int) $id . '.png';
        $mime = Storage::mimeType($avatar);

        if (Storage::exists($avatar)) {
            $headers = [
                'Content-Type'        => $mime,
                'Content-Disposition' => 'attachment; filename="' . $avatar . '"',
            ];

            // Downloading an image from aws s3 and displaying it from the server is idiotic
            return response(Storage::get($avatar), 200, $headers);
        }

        return response()->download(public_path('default/avatar.png'));
    }
}

POST Form Data as JSON with Fetch API in JavaScript

async function getData(e) {
    e.preventDefault()

    let response;

    try {
        const formData = new FormData(e.target)

        response = await fetch('/web/api/add', {
            method: 'POST',            
            // body: JSON.stringify({ username: 'example', email: 'email@example.org' }),
            body: formData,
            headers: {
              'Accept': 'application/json',
              'Content-Type': 'application/json',
              'X-CSRF-TOKEN': '{{ csrf_token() }}'
            }
        });

        if (!response.ok) {
            const json = await response.json();
            console.log(json);
            throw new Error('Response status: ' + response.status);
        }

        const json = await response.json();
        console.log(json);
    } catch (error) {
        console.error(error.message);
    }
}

Redirect with javascript fetch

Laravel

Route::get('/redirect', function () {
    return redirect('/redirect-here-now', 301);
});

Js

fetch('/redirect', { redirect: 'follow' }).then(res => {
    if(res.redirected) {
        window.location.href = res.url
    }
}).catch(function(err) {
    console.log(err)
})
<?php
// use App\Models\Post;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Storage;
// Js onerror url fetch
Route::get('/img/url', function () {
$path = request('path') ?? '/default/avatar.webp';
if (Storage::exists($path)) {
return Storage::url($path);
} else {
return '/default/avatar.webp';
}
});
// Image response from storage
Route::get('/img/show', function () {
$path = request('path') ?? public_path('/default/avatar.webp');
if (Storage::exists($path)) {
return Storage::response($path);
} else {
return response()->file('/default/avatar.webp');
}
});
// Use image response example
Route::get('/img', function () {
return '<img src="/img/show?path=avatars/1.webp">';
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment