enlinea777/laravel-uploader

用于管理并上传 Laravel 10 文件的包

1.0 2023-11-10 18:53 UTC

This package is auto-updated.

Last update: 2024-09-10 20:36:12 UTC


README

为文件上传提供 Laravel 后端

1.需求

建议使用 PHP 版本 8.2.x+ 和 Laravel 框架版本 10 来安装此包

2.安装

composer require enlinea777/laravel-uploader

您可以通过常规表单提交或 AJAX 调用(自行构建或任何第三方插件)将文件上传到后端。

注意:

  • 表单提交只支持单个文件上传。对于多个文件上传,您应使用 AJAX 来并行发送文件。

  • 该包还包括来自 Krajee 的前端文件输入插件,用于快速演示 AJAX 上传。包中包含的资产几乎是最小的,可能不是最新的。您应查阅http://plugins.krajee.com/file-input以获取插件的最新版本和更高级的使用案例

  • 可以通过运行 npm install bootstrap-fileinput 来安装 Krajee 插件的全版本。

  • 为了使用包含的前端资产,请运行 php artisan vendor:publish --tag=enlinea777_fileupload.assets

3.使用方法

3.1 在控制器中

首先,在控制器构造函数中为注入 FileUpload 服务,您需要指定 Enlinea777\LaravelUploader\Contracts\FileUpload 类型。

use Enlinea777\LaravelUploader\Contracts\FileUpload;
-----------------
protected $fileupload;

public function __construct(FileUpload $fileupload)
{
    $this->fileupload = $fileupload;
}

然后,在处理文件上传请求的方法中,您将调用

$this->fileupload->handle(Request $request, string $fieldname, array $uploadSettings)

其中

  • $request:完整的 Laravel 请求对象
  • $fieldname:前端文件输入字段的名称
  • $uploadSettings(可选):用于自定义后端行为的内联设置

$uploadSettings 是一个关联数组,具有以下可能的键

  • directory:包含您上传文件的根目录
  • disk:文件上传的存储磁盘。有关更多详细信息,请参阅 Laravel 官方文档,例如:publics3
  • maxFileSize(以字节为单位):后端可以接受的最大上传文件大小
  • allowedExtensions:可接受的文件扩展名数组,例如:['jpg', 'png', 'pdf']

后端默认设置如下

- 'directory': 'media'
- 'disk': 'public'
- 'maxFileSize':  50 MB
- 'allowedExtensions': 'png','jpg','jpeg','mp4','doc','docx','ppt','pptx','xls','xlsx','txt','pdf'

您可以使用以下 .env 中的环境变量来更改这些默认设置

  • ENLINEA777_LARAVEL_UPLOADER_DEFAULT_DISK
  • ENLINEA777_LARAVEL_UPLOADER_DEFAULT_DIRECTORY
  • ENLINEA777_LARAVEL_UPLOADER_DEFAULT_MAX_FILE_SIZE(以字节为单位)

注意:内联设置将覆盖默认设置

如果上传成功,则 $this->fileupload->handle(Request $request, string $fieldname, array $uploadSettings) 将返回以下数据,以便进一步持久化到数据库

[
    'filename' => 'the original file name',
    'path' => 'path to file location relative to the disk storage',
    'url' => 'public url to access the file in browser',
    'disk' => 'name of storage disk'
]

如果上传的文件无效,则将返回 false,并将错误消息设置为 $this->fileupload->uploadError

3.2 在前端视图中

3.2.1 正常表单上传

(仅支持单个文件上传)

示例:

<form action="/upload" method="POST" role="form" enctype="multipart/form-data">
    @csrf()
    <input class="form-control" type="file" name="photo" id="photo" />
    <input type="submit" name="submit" value="Upload" />
</form>

3.2.2 使用 Krajee 的默认前端资产进行 AJAX 上传

(支持并行请求发送多个文件)

示例:

<!DOCTYPE html>
<html>
<head>
    <title>File Upload</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link href="{{ mix('/css/app.css') }}" rel="stylesheet">
    <script src="{{ mix('/js/app.js') }}"></script>

    <!-- You must embed fileinput CSS and Javascript as follows -->
    <script src="/vendor/fileupload/js/fileinput/fileinput.min.js"></script>
    <link href="/vendor/fileupload/css/fileinput/fileinput.min.css" rel="stylesheet">
</head>
<body>

<input class="form-control" type="file" name="photo" id="photo" multiple />


<script type="text/javascript">
    $(document).ready(function(){
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });
        $("#photo").fileinput(
            {
                uploadUrl: '/upload',
                maxFileCount: 5,
                maxFileSize: 10420, //in KBs
                allowedFileExtensions: ['jpg', 'png', 'pdf'],
                previewFileType:'any',
                showUpload: false
            }
        ).on("filebatchselected", function(event, files) {
            $("#photo").fileinput("upload");  
        });
    });
</script>
</body>
</html>

注意:当使用 Krajee 文件输入插件时,您必须在处理上传请求的控制器方法中返回以下 json 响应

if ($path = $this->fileupload->handle($request, 'photo', $uploadSettings)) {
    // Persist $path data to database
    return json_encode([]);
}

return json_encode([
    'error' => $this->fileupload->uploadError
]);

3.2.3 使用 @bkstar18/jquery-ajax-uploader 插件(由我编写)进行 AJAX 上传

您可以在https://github.com/enlinea777/jquery-ajax-uploader中查看其完整文档

示例使用:

a) 安装

  • npm install --save-dev @bkstar18/jquery-ajax-uploader

  • resources/js/bootstrap.js 中,放置以下行

try {
    window.Popper = require('popper.js').default;
    window.$ = window.jQuery = require('jquery');

    require('bootstrap'); 
    require('@bkstar18/jquery-ajax-uploader'); // Add this line
} catch (e) {}
  • 然后,使用 laravel-mix 编译您的资源:npm run production

  • 或者,如果您不想将此插件捆绑到主 app.js 中,可以在 webpack.mix.js 中放置以下行

mix.js('resources/js/app.js', 'public/js')
   .copy('node_modules/@bkstar18/jquery-ajax-uploader/dist/enlinea777-ajax-uploader.min.js', 'public/js/enlinea777-ajax-uploader.min.js') // Add this line
   .sass('resources/sass/app.scss', 'public/css');

然后,在您想使用该插件的任何视图中包含以下代码:<script src="/js/enlinea777-ajax-uploader.min.js"></script>。记住在使用插件之前加载 jQuery。

b) 在 HTML 部分

<div class="form-group">
    <label for="image-upload">Upload Images</label>
    <input type="file" class="form-control" name="image" id="image-upload" multiple>
    <div class="gallery" id="gallery"></div>
</div>

c) 在 JavaScript 部分

$(document).ready(function () {
    $('#image-upload').enlinea777_ajaxuploader({
        allowedExtensions: ['png','jpg','jpeg'],
        batchSize: 5,
        outerClass: 'col-md-12',
        uploadUrl: '/api/upload',
        beforeSend: (xhr) => {
            xhr.setRequestHeader('X-AUTHOR', 'TUANHA');
        },
        onResponse: (response) => {
            let res = JSON.parse(response)
            $('#gallery').append(`<img id=${res.data.filename} src="${res.data.url}" width="50px">`);
        }
    });
});

d) 在 Laravel 控制器方法中

public function upload(Request $request, FileUpload $fileupload)
{
    $data = $fileupload->handle($request, 'image', ['allowedExtensions' => ['jpg', 'png', 'jpeg']]);
    if (!$data) {
        return response()->json(['error' => $fileupload->uploadError], 422);
    }
    // Saving data to database
    return response()->json(['success' => "{$data['filename']} has been successfully uploaded", 'data' => $data], 200);
}

注意:
您应该确保页面 HTML 布局包含以下 <meta> 标签

<meta name="csrf-token" content="{{ csrf_token() }}">

否则,请求可能会被 Laravel 默认阻止。更多信息请查看 https://laravel.net.cn/docs/5.8/csrf#csrf-x-csrf-token

插件自动检查此 <meta> 标签的存在,获取其内容,并将 X-CSRF-TOKEN 标头与上传请求相关联。

或者,只有当<meta> 标签不存在(可能您不想使用,或者由于某些原因),那么您可以在发送文件到服务器之前通过 beforeSend(xhr) 插槽包含 X-CSRF-TOKEN 请求标头,如下所示

$(document).ready(function () {
    $('#image-upload').enlinea777_ajaxuploader({
        ...
        beforeSend: (xhr) => {
            xhr.setRequestHeader('X-CSRF-TOKEN', {!! json_encode(csrf_token()) !!});
        },
        ...
    });
});

3.3 物理删除上传的文件

您可以根据以下示例物理删除上传的文件

$this->fileupload->delete($photo->disk, $photo->path)  

在此示例中,photos 表必须具有 diskpath 列以持久化 photo 实例。

您应该在删除数据库中相关的记录后才能物理删除上传的文件。