djam90 / user-image-handling
在 Laravel 中处理用户上传的图像
Requires
- php: >=5.4.0
- intervention/image: ^2.4
Requires (Dev)
- barryvdh/laravel-debugbar: ^3.1
- orchestra/testbench: ~3.5.0|~3.6.0
- phpunit/phpunit: ^6.2|^7.0
This package is auto-updated.
Last update: 2024-09-25 06:52:56 UTC
README
此包不完整
安装
- 运行
composer require serosensa/user-image-handling @dev
- 运行
php artisan vendor:publish --tag=userimage-js-assets
- 在创建主 vue 实例之前,但在 require vue 之后,将
require('./user-image/userImageApp.js')
添加到主 app.js 文件中 - 运行
php artisan vendor:publish --tag=userimage-sass-assets
- 在主 scss 文件中的 vendor 部分(在设置之后但在任何自定义样式之前)添加
@import "user-image/user-image"
用法 & 功能
- 此包附带一组默认路由和默认 UserImageController
- 您可以使用这些默认路由和相关方法,或者从 UserImageController 复制相关方法并根据需要修改。
- 如果您选择创建自己的控制器,您仍然可以利用 ImageService 中的有用方法。例如,要从 ImageService 访问方法,扩展 UserImageBaseController
class MyImageController extends UserImageBaseController
- 上传图像被视为与创建图像数据库记录的独立步骤。确保完成这两个步骤,以便可以检索图像。
### 默认行为
图像上传
使用 file-upload-fetch
组件,向 fetch-image-upload 发送请求,并使用 UserImageController@fetchImageUpload 组件接收包含位置等文件数据的 json,并发出事件 file-upload
到其父组件 //TODO 使用 v-model 优雅地传递它。父组件负责捕获此事件并适当地使用数据(例如创建数据库记录)
保存图像记录
将 file-upload-fetch 生成的 fileData 传递给 ImageService@saveImageRecords;将保存图像记录到默认的 UploadedImages
表(有关更多信息,请参阅此说明)。您可以将模型名称(例如 Article)传递以将图像绑定到数据库中的特定相关模型。
上传并保存记录
方法 UserImageController@fetchImageUploadAndRecord
通过组合上述功能处理这两个步骤。只需创建一个指向此方法的路由,并将 file-upload-fetch 上的 post-url 设置为此路由即可。
异步上传图像
上传文件并接收可用于从服务器请求图像的 json
- 使用
file-upload-fetch
vue 组件 Props- postUrl(可选:默认 /fetch-file-upload)
- 未使用 - fileDest - 公共磁盘中的一个可写文件夹
- 未使用 - parentIdentity(数组:父模型,id)- 用于确保正确的 vue 父组件捕获事件。在控制器中未使用
- multiple(可选:默认 false)
- 显示文件上传输入
- 通过 postUrl 达到的控制器应将图像文件保存到存储。方法
ImageService@fetchImageUpload
执行此操作并返回 json。请参阅 ImageService 方法 - 期望在上传后接收包含文件数据的 json。
- TODO 在此组件中显示上传的文件,以及现有的上传文件(可选)
- 在成功上传后,通过事件总线发出事件
file-upload
,其中包含 parentIdentity 和 fileData。父组件可以捕获并使用此数据 //TODO 将此数据添加到父组件中,使用 v-model
通过 POST 上传图像(未完全测试)
- 使用常规文件上传字段向控制器提交。
- 控制器可以使用
ImageService@imageUpload
来重命名和调整文件大小,并使用ImageService@saveImageRecords
在 UploadedImage 表中创建数据库记录(见 ImageService 方法)
保存 / 存储图像记录
- 一旦上传了图像,将其记录保存到相关的数据库表中
- 可以从
ImageService@imageUpload
返回的数据中获取这些信息 - 该包创建了一个默认的 uploaded_images 表(见 图像存储和检索)
- 可以使用
ImageService@saveImageRecords
方法将记录保存到默认表(见 ImageService 方法) - 还有默认的已上传图像模型(见 默认已上传图像模型)
- 或者,根据需要将记录保存到其他表中
- 通过
file-upload-fetch
组件上传的图像将默认将图像数据返回到父表单。在控制器中创建数据库记录时保存父表单。或者,将文件上传获取的 postUrl 设置为创建数据库记录的控制器
ImageService 方法
ImageService@imageUpload
参数 - 请求对象 - 文件目标 - 包含图像的字段名称(可选,默认:images) - 调整图像文件宽度的像素(可选,默认:2000px)必须在表单中的每个文件输入字段中运行一次。接受单个或多个图像。不运行验证 - 在调用之前进行验证 - 返回 文件数据的数组,即使字段中只有一个文件
ImageService@fetchImageUpload
使用 ImageService@imageUpload
- 相同的参数 验证图像(TODO 处理字段中的多个文件) - 返回 文件数据的 json
ImageService@saveImageRecords
//TODO 未测试 将图像记录保存到默认的 UploadedImages
表。 参数 - 上传的图像数据(单个图像) - 父模型对象(可选,默认:null)期望上传的图像数据包含文件名和路径等详细信息。从 ImageService@ImageUpload
返回的数据是合适的。接受图像数组或单个图像 TODO 这是否工作?正在测试图像数据是否是数组,但单个图像仍然是一个数组吗?替代文本在下面。接受单个图像的数据 - 应在 foreach 循环中运行以处理多个图像 如果发送了父对象,则将父模型名称和父 Id 保存到图像记录中。否则,这些值为空。 - 返回 记录数组或单个记录
ImageService@imageEditorSave
处理由 image-editor
组件发送的数据 参数 - 图像实例(在调用控制器中检索图像并通过传递) - 请求对象 返回 组件使用的图像数据的 json
图像存储和检索
默认 UploadedImage 表
//TODO - 必须手动复制迁移,包中未正常工作 存储图像数据的记录 由 ImageService@saveImageRecords
使用 可选与父模型和 Id 相关 - 这可以用来从表中检索图像,例如,通过调用 UploadedImage::where(parent_model, 'article')
或 UploadedImage::where('parent_model', 'article')->where('parent_id', $parentId)
或者,将此表的 id
存储在枢纽表中,以便其他模型按需访问。它也是
必需字段 - 文件名 - 路径 可选字段 - 文件类型 - 文件大小 - category_id - 标题 - is_primary(默认:0) - is_shown(默认: 1) - parent_model - 表示父模型的模型名称 - parent_id - 父 Id
默认 UploadedImage 模型
扩展此模型以添加所需的功能 - class MyUploadedImageModel extends Serosensa\UserImage\UploadedImage
。设置日期和 guarded 在 created_at 和 updated_at 字段上
- 方法?
显示 / 编辑现有图像
Image-display 组件
- 使用
image-display
vue 组件来显示每个图像(例如,使用 v-for) 属性 - 图像 - 显示图像和相关数据
- 使用插槽
info-panel-default
来覆盖默认数据 - 使用插槽
info-panel-extra
添加额外数据 - 在信息面板外部还有一个默认插槽
- 使用插槽
图像编辑组件
- 在图像显示组件内,添加
image-editor
组件的 Props- image,
- postUrl(不含图像ID或'/')
- categories(可选)
- 允许
- 更改 is_shown 值
- 更改 is_primary 值
- 更新说明
- 旋转图像
- 设置类别(可选通过插槽)
- 显示一个编辑按钮,包含一个用于编辑图像的模态框。具有一些默认选项和多个插槽
- 插槽
title
- 插槽
fields-default
显示默认编辑字段。如有需要可覆盖。 - 插槽
categories
如果需要类别选择器。如果使用,设置slot-scope="categoriesScope"
- 插槽
fields-extra
用于任何额外字段 - 插槽
label_is_primary
- 插槽
label_is_shown
- 插槽
label_caption
- 插槽
subtext_caption
在说明下方添加额外文本。验证应在控制器/自定义请求中执行。验证失败时,Laravel 返回一个包含错误的 JSON 数组,编辑窗口将在适当的字段旁边显示这些错误。
- 插槽
<image-display :image="{{$image}}" :categories="{{$propertyImageTypes}}" class="">
<image-editor class="" :image="{{$image}}" post-url="{{route('propertyImageUpdate', $image->id)}}" :categories="{{$propertyImageTypes}}">
<div slot="title" class="title">Edit Image</div>
</image-editor>
</image-display>
图像编辑类别
在 imageEditor 内显示类别选择器
- 在 image-editor 上传递类别数组
categories
prop - 每个类别必须至少有一个 id 和一个 name。组件使用每个类别的 'name' 字段生成 categoryName
- 确保图像有一个
category_id
字段 - 在利用插槽的元素上添加
slot-scope="categoriesScope"
,这允许插槽和父组件之间共享数据。以下示例创建单选按钮以选择类别
<div slot="categories" slot-scope="categoriesScope" class="form-row">
<label for="">Image Type:</label>
<span v-for="category in categoriesScope.categories">
<label for="category_id">{{ option.name }}</label>
<input type="radio" :value="category.id" v-model="categoriesScope.model.category_id">
</span>
</div>
字段错误组件
- 在可能返回错误的任何字段旁边使用
field-errors
组件 - 显示给定字段的全部错误
- 传递错误对象和要显示错误的字段名称
<field-errors :errorObject="errors.is_primary"></field-errors>
详细内容
//TODO - 一些内容已被上述内容取代/需要更新
JS 文件(vue / 前端通用)
- 文件
userImageApp.js
注册了包提供的所有 vue 组件 - 通过运行
php artisan vendor:publish --tag=userimage-js-assets
导出此文件 - 这会将所有 JS 文件导出到resources/assets/js/user-image
- 警告:如果直接修改这些文件,它们可能在包更新时被覆盖。要强制更新并覆盖文件,请将
--force
添加到发布命令 - 在创建主 vue 实例之前但在引入 vue 之后,在应用的 main app.js 中引入此文件
require('./user-image/userImageApp.js');
样式
- 将 _user-image.scss 文件包含在您的 main sass 文件中。在包含您自己的样式表之前包含此文件,以便您可以轻松覆盖样式
- 通过运行
php artisan vendor:publish --tag=userimage-sass-assets
发布此文件 - 这会将 scss 文件导出到resources/assets/sass/user-image
图标
- 本包中的所有图标都具有类
image-editor-icon
- 可以通过设置
$user-image-icon-color-1
和$user-image-icon-color-2
的值来重新着色图标 - 在引入供应商样式表之前(例如在设置中)设置这些值以覆盖默认值。某些图标可能只会使用 color1。 - 您也可以通过类来覆盖样式,以在不同上下文中样式化图标
- 图标作为 JS 文件存在于 /vendor/serosensa/icons 中,由每个模板根据需要引入
图像上传 - 通过 ImageService
- ImageService 处理图像文件上传的所有方面
- 它必须传递包含上传图像文件表单的 $request
- 该服务可以处理每个字段上传多个图像
- 如果设置了唯一字段名称,则服务可以处理表单中每个字段上传多个文件
- 每个上传字段可以有自己的目标文件夹
- 目标文件夹应添加到 .gitignore 中,因为它们将独立于源代码在服务器上更改
- imageService 将文件保存到 config/filesystems 中定义的 'public' 磁盘。如果这是 /app/public 文件夹,则在此保存的文件通过其 URL 或文件名公开可见
文件目标 / 可写文件夹
上传文件要保存的文件夹必须是可写的。为此,请执行 chmod -R 777 public/foldername
图像上传表单
- 包含文件上传的表单必须具有
enctype="multipart/form-data
或参数 files => true(如果使用 LaravelCollective 表单) - 要按字段上传多个图像,请在字段中添加
multiple
并在视图文件中的字段名中添加[]
默认字段名 - 一个文件上传字段
- 默认情况下,
ImageService@imageUpload
函数期望有一个名为images
的上传字段。如果请求中只有一个上传字段,则可以使用此默认值,或者可以使用其他名称并传递给服务。
自定义字段名 - 一个或多个文件上传字段
- ImageService 必须为每个上传字段调用一次
- 文件上传字段必须具有唯一、自定义的名称,例如
thumbnail
控制器中的图像上传
- 请参阅
/examples
目录中的 ExampleController 以获取示例控制器函数 - ImageService 处理大部分图像操作 - 控制器只需调用 ImageService,传递值并保存结果数据。
- 在调用 imageService@imageUpload 之前,应验证上传的文件(以确保是正确的图像文件类型)。此包包括一个
IsValidImageRequest
,您可以将其使用。如果验证失败,这将返回一个错误包isValidImage
。 - 如果误用 imageService 而请求中没有文件,它将返回 null 而不是生成错误
- ImageService 总是返回一个包含图像数据的嵌套数组 - 不论上传的文件数量如何。循环此数组以提取每个图像的数据。
ImageService@imageUpload 功能
- 一旦调用,imageservice
- 循环每个图像
- 如果已存在同名文件,则重命名文件
- 将文件保存到指定的文件夹(在删除任何前导 / 之后,因为这会导致保存调整大小的文件时出现问题)
- 将文件调整到指定的最大宽度(除非是 svg)
- 返回一个包含每个图像数据数组的数组
- 然后应按调用函数所需的方式处理返回的数据 - 例如,将文件名保存到数据库中
图像旋转
image-editor
组件包含image-rotation
组件,但这也可单独使用。- 应将正在编辑的图像的数据库 ID 传递给 image-rotation 组件,例如
<image-rotation :image-id="image.id"></image-rotation>
- 当旋转按钮被点击时,组件会发出一个事件,该事件被编辑器收集并用于转换图像预览。
- 旋转值被添加到 imageData 中,因此传递到控制器,在那里它可以被使用。请参阅
ExampleController
以进行演示 -ImageService
处理实际的旋转,因此此功能可以在任何地方调用。 - 当编辑保存时,
image-display
组件会捕获来自 image-editor 的发出的事件。这会触发从磁盘重新加载更新的图像,因此更改(包括旋转和可能在未来启用的任何其他更改)都会反映在显示的图像中 image-editor
组件还会从磁盘重新加载图像并重置旋转值,以便下次加载时它是“新鲜的”- 从磁盘重新加载是通过将图像的src设置为
versionedImage
数据对象来完成的。在加载时,它设置为原始文件名,但在每次需要更新图像时(例如保存编辑时),都会通过调用makeVersionedImage()
函数来覆盖。此函数将随机版本号追加到文件名末尾,导致重新加载。
待办事项
- 添加表单/样式包作为依赖项(替换此包中现有的包含文件?)
- IsValidImageRequest没有经过适当的测试 - 在ImageService@fetchFileUpload中验证文件上传
有用参考资料
- 创建一个包 - https://devdojo.com/blog/tutorials/how-to-create-a-laravel-package
- 针对Laravel的包开发,包括有关发布文件的信息 - https://laravel.net.cn/docs/5.6/packages
- 本地开发包 - https://johannespichler.com/developing-composer-packages-locally/