Why are you storing the images as blob, that is really bad practice?
However, this guide should help you with the upload part.
https://larainfo.com/blogs/laravel-8-image-file-upload-with-inertia-js-vue-3-example
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
Hi, I have the following situation and I do not know how to manage it.
In my vue3 I have this Inertia form
let form = useForm({
name: props.product.name,
description: props.product.description,
photos: store.getPhotos,
});
and somewhere below I submit it like so:
function submit() {
form.post(route('products.update', { id: props.product.id }));
}
The problem is that in laravel I have all the photos in blob format and I do not know how should I use FormData with inertia and vue.
Can anyone help, please?
Thanks!
Why are you storing the images as blob, that is really bad practice?
However, this guide should help you with the upload part.
https://larainfo.com/blogs/laravel-8-image-file-upload-with-inertia-js-vue-3-example
@stefanp here is what I did in my project (installed version of vue is 3 but using vue2 syntax)
// template
<input
ref="coverPhoto"
@change="selectedCoverPhoto($event)"
type="file"
class="hidden"
>
<button
v-if="!coverPhotoPreview"
@click="$refs.coverPhoto.click()"
type="button"
class="bg-gray-200 border border-dashed border-gray-500 rounded-lg h-64 w-52 grid place-content-center text-gray-500 hover:text-gray-700 cursor-pointer hover:border-gray-700"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-10 w-10 mx-auto"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11a1 1 0 10-2 0v2H7a1 1 0 100 2h2v2a1 1 0 102 0v-2h2a1 1 0 100-2h-2V7z"
clip-rule="evenodd"
/>
</svg>
<h1 class="text-sm px-5">
Select book cover photo to upload
</h1>
</button>
// script
data() {
return {
form: this.$inertia.form({
cover_photo: '',
title: '',
excerpt: '',
author: '',
price: '',
category_id: '',
stock_count: '',
}),
coverPhotoPreview: '',
coverPhotoName: '',
showCoverPhotoEdit: false,
}
},
methods: {
submit() {
this.form.post(route('admin.books.store'))
},
selectedCoverPhoto(e) {
this.form.cover_photo = e.target.files[0]
this.coverPhotoName = this.$refs.coverPhoto.files[0].name
const reader = new FileReader()
reader.onload = (e) => {
this.coverPhotoPreview = e.target.result
}
reader.readAsDataURL(this.$refs.coverPhoto.files[0])
}
}
//controller
public function store(StoreBookRequest $request)
{
$request->validated();
$attributes = $request->except('cover_photo');
$attributes['slug'] = Str::slug($request->title . '-' . uniqid());
$attributes['cover_photo_path'] = $request->file('cover_photo')->store('cover-photos');
Book::create($attributes);
return Redirect::route('admin.books.index');
}
I think I know what is going on and I ask you to validate may thoughts.
I use this code which helps me to preview the image. I pass all files to addFiles method and within the addfiles method I process them witin UploadFile class (pretend you don’t see line 22) to prepare more data for the frontend.
It seems that I can preview the photo based on line 17. I do not want to save the photo and then see it. I want to see it first and after that to send it to laravel backend.
Also in addFiles(), I add the photos to my store - line 9.
For sending my form to laravel I use this piece of code and my laravel request looks like image_3 where my problem arises.
Well… finally I realised that i do not have to send the photo in blob format but in a file File object and for this I added the line 22 in the UploadableFIle class and now my request looks better like in image_4
What do you think about my version?
I try to include photos from imgur but I do not know why is not working so I will post the code below:
import { useStore } from "@/Stores/pinia";
export default function () {
const store = useStore();
function addFiles(newFiles) {
let newUploadableFiles = [...newFiles]
.map((file) => new UploadableFile(file));
store.addPhotos(newUploadableFiles);
}
return { addFiles };
}
class UploadableFile {
constructor(file) {
this.id = Math.floor(Math.random() * (1000000 - 10000) + 1000000); //todo: alta varianta de a da un id pozei pentru a o putea sterge
this.blob = URL.createObjectURL(file);
this.is_new = true;
this.is_packaging = 0;
this.original_name = file.name;
this.request_front_deletion = false;
this.file_obj = new File([URL.createObjectURL(file)], file.name); !! this is line 22
}
}
let form = useForm({
name: props.product.name,
description: props.product.description,
photos: store.getPhotos,
});
function submit() {
form.post(route('products.update', { id: props.product.id }));
// Inertia.post(route('products.update', {id: props.product.id}), form, {forceFormData: true});
}
array:3 [▼ // app/Http/Controllers/ProductController.php:103
"name" => "nume p"
"description" => "desc p"
"photos" => array:6 [▼
0 => array:14 [▶]
1 => array:14 [▶]
2 => array:14 [▶]
3 => array:7 [▼
"id" => "1816946"
"blob" => "blob:http://prefix.test/5965a27a-0ee6-44e1-8fee-c504c32110b3"
"is_new" => "1"
"is_packaging" => "0"
"original_name" => "category-page-04-image-card-03.jpg"
"request_front_deletion" => "1"
array:3 [▼ // app/Http/Controllers/ProductController.php:103
"name" => "nume p"
"description" => "desc p"
"photos" => array:6 [▼
0 => array:14 [▶]
1 => array:14 [▶]
2 => array:14 [▶]
3 => array:7 [▼
"id" => "1816946"
"blob" => "blob:http://prefix.test/5965a27a-0ee6-44e1-8fee-c504c32110b3"
"is_new" => "1"
"is_packaging" => "0"
"original_name" => "category-page-04-image-card-03.jpg"
"request_front_deletion" => "1"
"file_obj" => Illuminate\Http\UploadedFile {#337 ▼
-test: false
-originalName: "category-page-04-image-card-03.jpg"
-mimeType: "application/octet-stream"
-error: 0
#hashName: null
path: "/tmp"
filename: "phpcP9srG"
basename: "phpcP9srG"
pathname: "/tmp/phpcP9srG"
extension: ""
realPath: "/tmp/phpcP9srG"
aTime: 2022-12-23 10:53:41
mTime: 2022-12-23 10:53:41
cTime: 2022-12-23 10:53:41
inode: 1211465
size: 60
perms: 0100600
owner: 501
group: 20
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
]
Please or to participate in this conversation.