您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
图片上传保存逻辑(laravel11+breeze+inertia+vue3实现图片上传)
发布时间:2024-10-31 23:00:35编辑:雪饮阅读()
-
inertia前端配置
图片上传说白了其实就是文件上传了。
在laravel11中以breeze+inertia+vue3这种入门套件部署的.
那么首先从前端来着手。
像我们之前创建project的界面现在就再增加一个project的头像的输入。
则form表单如
Y:\root\example-app\resources\js\Pages\Project\Partials\UpdateProjectInformationForm.vue中的表单局部代码如:
<form
@submit.prevent="submit"
class="mt-6 space-y-6" enctype="multipart/form-data"
>
<div>
<InputLabel for="name" value="Name" />
<TextInput
id="name"
type="text"
class="mt-1 block w-full"
v-model="form.name"
required
autofocus
autocomplete="name"
/>
<InputError class="mt-2" :message="form.errors.name" />
<input type="file" @input="form.avatar = $event.target.files[0]" />
<progress v-if="form.progress" :value="form.progress.percentage" max="100">
{{ form.progress.percentage }}%
</progress>
</div>
<div class="flex items-center gap-4">
<PrimaryButton :disabled="form.processing">Save</PrimaryButton>
<Transition
enter-active-class="transition ease-in-out"
enter-from-class="opacity-0"
leave-active-class="transition ease-in-out"
leave-to-class="opacity-0"
>
<p
v-if="form.recentlySuccessful"
class="text-sm text-gray-600 dark:text-gray-400"
>
Saved.
</p>
</Transition>
</div>
</form>
这里有enctype="multipart/form-data"是我们所熟知的,上传文件的form一般是要声明这个的,但这里是否多余,我没有尝试。按理来说这种inertia新框架应该是可以忽略,文档中也没有写,但我测试过程中没有成功,当然也是修改了好几处,或许这个也是影响因素之一。
再者就是<input type="file" @input="form.avatar = $event.target.files[0]" />是那个原生的文件上传input。
<progress v-if="form.progress" :value="form.progress.percentage" max="100">
{{ form.progress.percentage }}%
</progress>
这个其实是为了就是表单提交有个进度,毕竟包含有了文件了,所以表单会比较大。当然这个也是inertia实现的。
那这里你可能也看到了我们的表单提交方法调用了一个名为submit的方法,是的,这里是需要单独封装一个提交方法。因为用上篇中默认的那个已经不行了。(也可能有其他原因,反正这里也修改了就促成最后的成功,但inertia上面也有说明针对laravel是可能要进行请求欺骗下)。
另外需要补充说明下inertiajs文档有说:
在 0.8.0 版本之前,Inertia 不会自动将请求转换为 .如果您使用的是此版本之前的 Inertia 版本,则需要手动执行此转换。FormData。
但我这里是1.2.0。
所以这个暂时可以不用处理了。
Inertia的版本可以参考如Y:\root\example-app\node_modules\@inertiajs\core\package.json中有显示的。
那么我封装的submit则如
function submit() {
router.post(`/project`, {
_method: 'patch',
avatar: form.avatar,
name:form.name
})
}
这里的_method是patch,是因为我们之前的update方法于project控制器在web.php中的路由方法是patch,这里用post伪装成patch了。
虽然PUT和PATCH请求在理论上可以使用multipart/form-data编码,但在实际应用中可能会受到一些限制或需要额外的配置。
这里用到了router,而不是像之前一样用route,所以这里需要声明下
import { useForm, usePage,router } from '@inertiajs/vue3';
结果回显处理
我这里的设计是project上传成功后进入到project列表,然后project列表中要展示project的头像。
所以之前的Y:\root\example-app\resources\js\Pages\Project\Partials\Project.vue
这个由列表进行循环的project的组件就新增avatar字段的展示
<script setup>
defineProps(['project']);
</script>
<template>
<div class="p-6 flex space-x-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-600 -scale-x-100" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
<div class="flex-1">
<div class="flex justify-between items-center">
<div>
<span class="text-gray-800">{{ project.name }}</span>
<img :src="project.avatar" />
</div>
</div>
</div>
</div>
</template>
图片上传保存逻辑
回到之前的project控制器
Y:\root\example-app\app\Http\Controllers\ProjectController.php
为其project创建的update方法进行实现图片的上传。
public function update(ProjectUpdateRequest $request):RedirectResponse
{
$this->log(var_export($request->user(),true));
$this->log("uid:".$request->user()->id);
$file=$request->file('avatar');
//存储于可访问的public(相对而言,laravel11默认配置是local,是private(同样相对而言,因为默认的laravel11的符号链接storage指向是public))
$path=$file->store('','public');
//生成访问url,形如:/storage/1.png/5QHGtDmuUgCCVtodClt059NpXf6OY4UERxc1cx9H.png
$url = Storage::url($path);
$uid=$request->user()->id;
$name=$request->input("name");
$project=new Project();
$project->uid=$uid;
$project->name=$name;
$project->avatar=$url;
$project->save();
return Redirect::route('project.index');
}
则你也可能看到了我们新增了avatar字段,所以project数据表里面同样也是需要增加的。
alter table project add column `avatar` char(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
生成符号链接
最后这一点也很重要,因为我们存储为laravel11中所谓的磁盘public中,但该public默认定义路径如
Y:\root\example-app\storage\app\public
该路径并非是我们的项目web访问根目录的那个public
如下命令就可以根据默认laravel11的filesystems.php里面的配置生成符号链接于我们项目根目录下的storage去引用storage\app\public。
命令如:
./vendor/bin/sail artisan storage:link
最后不出意外就是可以上传图片成功了
本期词汇
inertia 惰性 惯性
breeze 微风,和风
browse 随意的看,浏览
关键字词:laravel11,breeze,inertia,图片上传