Previewing an image before upload is a client-side concern handled entirely in JavaScript using the File API — the server-side handling (validation, storing the file) is identical to a plain image upload without a preview.
The form markup
The preview JavaScript
document.getElementById('avatar').addEventListener('change', function (event) {
const file = event.target.files[0];
const preview = document.getElementById('preview');
if (file) {
const reader = new FileReader();
reader.onload = function (e) {
preview.src = e.target.result;
preview.style.display = 'block';
};
reader.readAsDataURL(file);
}
});
FileReader.readAsDataURL() converts the selected file into a base64 data URL entirely in the browser, without touching the server — this is what lets the preview appear instantly, before the form is even submitted.
Server-side validation and storage
public function update(Request $request)
{
$request->validate([
'avatar' => 'required|image|mimes:jpeg,png,jpg,webp|max:2048',
]);
$path = $request->file('avatar')->store('avatars', 'public');
$request->user()->update(['avatar_url' => Storage::url($path)]);
return back()->with('success', 'Avatar updated.');
}
The mimes rule restricts the accepted file types at the server level — the client-side accept="image/*" attribute is a convenience for the file picker dialog, not a real security control, since it's trivial to bypass from outside the browser.
Why validation still matters even with a preview
A working preview only confirms the browser can render the selected file as an image — it says nothing about whether the file actually meets the server's size, dimension, or MIME-type requirements, which is exactly what the server-side validate() call is for.
Cleaning up the old avatar on replacement
if ($request->user()->avatar_url) {
Storage::disk('public')->delete(str_replace('/storage/', '', $request->user()->avatar_url));
}
Following the same cleanup principle covered for the CRUD image field elsewhere on this site, deleting the previous file before storing the replacement avoids orphaned files piling up in storage over repeated updates.