注:本教程代码适用于Laravel 5.1版本。

1、概述

Dropzone 是目前最好的免费文件拖拽上传库,它拥有很多特性和选项以便你可以使用多种方式来自定义。

在Laravel项目集成Dropzone对没有经验的新手来说有点棘手,所以接下来我想你给你们展示最优雅的解决方案。

这篇教程将包括以下内容: 自动 图片 上传

通过Ajax请求从Dropzone预览中直接移除图片

上传图片计数器

保存完整尺寸图片和图标尺寸版本

使用Intervention Image包调整图片尺寸和编码

保存图片数据到数据库

在服务器端生成唯一的图片名称

如果你还需要上传或裁剪图片,请参考上一篇教程: 在 Laravel 5 中使用 jQuery 插件 Croppic + Intervention Image 实现图片上传和裁剪 。

本教程的完整代码已公开在GitHub上: https://github.com/codingo-me/dropzone-laravel-image-upload

最终演示效果图如下:

2、项目基本配置

这里我们安装一个新的Laravel应用并创建包含数据库凭证信息的.env文件。

此外我们还要从 https://github.com/enyo/dropzone/tree/master/dist 下载样式和脚本文件,这些文件存放到 public/packages/dropzone 。

前端我们还是使用Bootstrap,相关文件存放在 public/packages/bootstrap 。

上面已经提到我们要使用Intervention Image扩展包来处理上传图片,并且这里我们会在Blade模板中用到html辅助函数,所以我们需要安装相关依赖,安装Intervention Image请参考: 在 Laravel 5 中集成 Intervention Image 实现对图片的创建、修改和压缩处理 ,而安装html请参考: Laravel 5 中使用 HtmlBuilder 及 URL::asset() 引入站内或站外的 css 和 js 文件 。

3、视图

本教程只包含单个页面用于上传图片,尽管这样我还是喜欢将布局和具体实现页面分开,我们编辑布局文件 layout.blade.php 如下: Image upload in Laravel 5.1 with Dropzone.js {!! HTML::style('/packages/bootstrap/css/bootstrap.min.css') !!} {!! HTML::style('/assets/css/style.css') !!} {!! HTML::script('https://code.jquery.com/jquery-2.1.4.min.js') !!} @yield('head')

接下来我们创建上传图片的视图文件 pages/upload.blade.php : @extends('layout')@section('head') {!! HTML::style('/packages/dropzone/dropzone.css') !!}@stop@section('footer') {!! HTML::script('/packages/dropzone/dropzone.js') !!} {!! HTML::script('/assets/js/dropzone-config.js') !!}@stop@section('content')

Images

{!! Form::open(['url' => route('upload-post'), 'class' => 'dropzone', 'files'=>true, 'id'=>'real-dropzone']) !!}

Drop images in this area {!! Form::close() !!}

Images are uploaded as soon as you drop them

Maximum allowed size of image is 8MB

Check Created with Sketch.

error Created with Sketch. @stop

在上传视图的 head 部分我们引入了Dropzone的默认样式,在 footer 部分我们传递默认的JavaScript文件以及我们自己的Dropzone配置文件。

内容部分包含两个部分,首先是上传表单然后是隐藏的图片预览区域,我是从Dropzone官网下载的预览模板代码,在配置文件中使用这个模板告诉Dropzone哪段HTML用于上传图片预览。

4、Dropzone配置

查看完整的Dropzone配置项列表参考 这里 ,对本项目来说我想从Dropzone一个一个上传文件,因为这样的话我就不需要循环遍历文件上传,并行上传文件数限制为100并且每个文件大小不能超过8M。

每个图片预览都对应一个删除链接,点击该链接Dropzone就会触发 removedfile 事件,该事件会创建上传/删除的Ajax请求,如果响应状态码是200,则对应图片计数器减少。 var photo_counter = 0;Dropzone.options.realDropzone = { uploadMultiple: false, parallelUploads: 100, maxFilesize: 8, previewsContainer: '#dropzonePreview', previewTemplate: document.querySelector('#preview-template').innerHTML, addRemoveLinks: true, dictRemoveFile: 'Remove', dictFileTooBig: 'Image is bigger than 8MB', // The setting up of the dropzone init:function() { this.on("removedfile", function(file) { $.ajax({ type: 'POST', url: 'upload/delete', data: {id: file.name}, dataType: 'html', success: function(data){ var rep = JSON.parse(data); if(rep.code == 200) { photo_counter--; $("#photoCounter").text( "(" + photo_counter + ")"); } } }); } ); }, error: function(file, response) { if($.type(response) === "string") var message = response; //dropzone sends it's own error messages in string else var message = response.message; file.previewElement.classList.add("dz-error"); _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]"); _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { node = _ref[_i]; _results.push(node.textContent = message); } return _results; }, success: function(file,done) { photo_counter++; $("#photoCounter").text( "(" + photo_counter + ")"); }}

该配置文件底部如果上传成功图片计数器增加。

5、上传逻辑

我习惯将特定逻辑放到Repository类,在本项目中我使用 ImageRepository 这个类,该类存放在 app/Logic/Image/ImageRepository.php 。

目前这个类只做两件事,上传单个文件以及删除指定文件,我们将整个Repository类注入到 ImageController 中: image = $imageRepository; } public function getUpload() { return view('pages.upload'); } public function postUpload() { $photo = Input::all(); $response = $this->image->upload($photo); return $response; } public function deleteUpload() { $filename = Input::get('id'); if(!$filename) { return 0; } $response = $this->image->delete( $filename ); return $response; }}

因此对这个控制器而言我需要三个路由:显示上传表单,上传以及删除请求: Route::get('/', ['as' => 'upload', 'uses' => 'ImageController@getUpload']);Route::post('upload', ['as' => 'upload-post', 'uses' =>'ImageController@postUpload']);Route::post('upload/delete', ['as' => 'upload-remove', 'uses' =>'ImageController@deleteUpload']);

ImageController 的 postUpload 方法将用户上传请求转发到 ImageRepository 类对应的 upload 方法。这个 upload 方法首先会验证输入,然后为上传文件分配唯一的文件名,再然后保存原始尺寸图片到指定目录,同时将图标尺寸图片保存到其它目录,此外还要保存到数据库以便Laravel可以跟踪图片上传记录。为此我们需要创建迁移文件并运行迁移命令: increments('id'); $table->text('original_name'); $table->text('filename'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('images'); }}

我已经提过了上传文件将会保存为两种尺寸,此外可能还要生成缩略图并对图片编码,要实现这些功能,我们需要使用Intervention Image扩展包: fails()) { return Response::json([ 'error' => true, 'message' => $validator->messages()->first(), 'code' => 400 ], 400); } $photo = $form_data['file']; $originalName = $photo->getClientOriginalName(); $originalNameWithoutExt = substr($originalName, 0, strlen($originalName) - 4); $filename = $this->sanitize($originalNameWithoutExt); $allowed_filename = $this->createUniqueFilename( $filename ); $filenameExt = $allowed_filename .'.jpg'; $uploadSuccess1 = $this->original( $photo, $filenameExt ); $uploadSuccess2 = $this->icon( $photo, $filenameExt ); if( !$uploadSuccess1 || !$uploadSuccess2 ) { return Response::json([ 'error' => true, 'message' => 'Server error while uploading', 'code' => 500 ], 500); } $sessionImage = new Image; $sessionImage->filename = $allowed_filename; $sessionImage->original_name = $originalName; $sessionImage->save(); return Response::json([ 'error' => false, 'code' => 200 ], 200); } public function createUniqueFilename( $filename ) { $full_size_dir = Config::get('images.full_size'); $full_image_path = $full_size_dir . $filename . '.jpg'; if ( File::exists( $full_image_path ) ) { // Generate token for image $imageToken = substr(sha1(mt_rand()), 0, 5); return $filename . '-' . $imageToken; } return $filename; } /** * Optimize Original Image */ public function original( $photo, $filename ) { $manager = new ImageManager(); $image = $manager->make( $photo )->encode('jpg')->save(Config::get('images.full_size') . $filename ); return $image; } /** * Create Icon From Original */ public function icon( $photo, $filename ) { $manager = new ImageManager(); $image = $manager->make( $photo )->encode('jpg')->resize(200, null, function($constraint){$constraint->aspectRatio();})->save( Config::get('images.icon_size') . $filename ); return $image; } /** * Delete Image From Session folder, based on original filename */ public function delete( $originalFilename) { $full_size_dir = Config::get('images.full_size'); $icon_size_dir = Config::get('images.icon_size'); $sessionImage = Image::where('original_name', 'like', $originalFilename)->first(); if(empty($sessionImage)) { return Response::json([ 'error' => true, 'code' => 400 ], 400); } $full_path1 = $full_size_dir . $sessionImage->filename . '.jpg'; $full_path2 = $icon_size_dir . $sessionImage->filename . '.jpg'; if ( File::exists( $full_path1 ) ) { File::delete( $full_path1 ); } if ( File::exists( $full_path2 ) ) { File::delete( $full_path2 ); } if( !empty($sessionImage)) { $sessionImage->delete(); } return Response::json([ 'error' => false, 'code' => 200 ], 200); } function sanitize($string, $force_lowercase = true, $anal = false) { $strip = array("~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]", "}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—", "—", "–", ",", "", "/", "?"); $clean = trim(str_replace($strip, "", strip_tags($string))); $clean = preg_replace('/\s+/', "-", $clean); $clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ; return ($force_lowercase) ? (function_exists('mb_strtolower')) ? mb_strtolower($clean, 'UTF-8') : strtolower($clean) : $clean; }}

上传方法会验证 Image 模型中指定的字段规则,目前该规则只是限定上传图片的扩展。

在 upload 方法之后我们使用 reateUniqueFilename 方法为图片返回唯一文件名。

当唯一文件名返回后,我们将图片和对应文件名传递到 original 方法,该方法负责保存完整尺寸图片,对小尺寸图标图片我们使用 icon 方法进行处理。

这两个尺寸图片都保存好了之后,系统会在图片表 images 中创建一条新纪录。

你可能已经注意到了我将图片上传目录存放在了配置文件中,当然你可以自定义存放目录或者直接使用Laravel内置的方法。 env('UPLOAD_FULL_SIZE'), 'icon_size' => env('UPLOAD_ICON_SIZE'),];

要让应用正常工作还需要将 .env.example 文件拷贝到 .env 文件,并且设置相应的配置值。注意到最后两个配置项的上传目录需要以 / 结尾,以我本地配置为例: UPLOAD_FULL_SIZE=F:/xampp/htdocs/nonfu/dropzone-laravel-image-upload/public/images/full_size/UPLOAD_ICON_SIZE=F:/xampp/htdocs/nonfu/dropzone-laravel-image-upload/public/images/icon_size/

删除方法接收文件名并检查数据库中是否包含,然后在对应文件在是否存在于指定目录,如果两项都符合则该图片会被删除。

想要更加轻松地使用DropzoneJS实现图片上传,可以使用Laravel扩展包 Dropzoner 。

声明:本文为译文,原文: https://tuts.codingo.me/laravel-5-1-and-dropzone-js-auto-image-uploads-with-removal-links

dropzone.js php,Laravel 5.1 中基于 Dropzone.js 实现图片拖拽上传及删除功能相关推荐

  1. 使用jQuery开发一个基于HTML5的漂亮图片拖拽上传web应用

    昨天我们介绍了一款HTML5文件上传的jQuery插件:jQuery HTML5 uploader,今天我们将开发一个简单的叫upload center的图片上传程序,允许用户使用拖拽方式来上传电脑上 ...

  2. js 监听 复制图片 拖拽上传文件 并填充到markdown编辑器

    文章目录 效果 获取粘贴的文件 获取拖拽的文件 发送请求 生成markdown 语句 实现逻辑代码(主要实现) 后端代码 效果 获取粘贴的文件 const { clipboardData } = e; ...

  3. Dropzone.js实现文件拖拽上传

    dropzone.js是一个开源的JavaScript库,提供 AJAX 异步文件上传功能,支持拖拽文件.支持最大文件大小.支持设置文件类型.支持预览上传结果,不依赖jQuery库. 使用Dropzo ...

  4. 实现拖拽上传文件的一款小控件——dropzone

    由于专注所以专业.非常多小巧的东西乍一看非常不起眼,却在特定的领域表现不俗,就是由于集中了热情. dropzone就是这样一款小控件,实现拖拽上传.它不依赖于其他像jquery等JS库.并且支持多方面 ...

  5. js使用input上传文件夹、拖拽上传文件夹并将文件夹结构展示为树形结构

    一.实现效果 左侧区域支持选择一个系统中的文件夹,或者将文件夹拖拽到这个区域进行上传,右侧区域可以将文件夹的结构展示为树形结构. 二.代码实现 由于需要使用树形插件zTree,这个插件是依赖于jque ...

  6. js实现文件拖拽上传并显示待上传的文件列表

    此文章中完整的代码在我的github中:https://github.com/LiuFeng1011/WebTest/tree/master/upload 首先实现html页面的内容: <bod ...

  7. dropzone拖拽上传组件使用全记录

    原文链接: dropzone拖拽上传组件使用全记录 公司有一个需求是把附件上传优化成可以通过拖拽本地文件来上传的效果,找了一圈都没有找到特别简单好用的组件,最后还是决定使用github上1.6万sta ...

  8. 原生js实现拖拽上传文件

    原生js实现拖拽上传文件 <!DOCTYPE html> <html lang="en"><head><meta charset=&quo ...

  9. JavaScript 文件拖拽上传插件 dropzone.js 介绍

    dropzone.js 是一个开源的 JavaScript 库,提供 AJAX 异步上传功能. 安装 下载dropzone.js文件并添加到页面中即可.Dropzone 不依赖 jQuery 框架. ...

最新文章

  1. Selenium提取数据之标签对象提取文本内容和属性值
  2. 给Resnet加人工经验提升30%的准确率
  3. python三引号注释_python3学习笔记(三):注释和字符串
  4. 三元一次方程组步骤_[七年级网上课堂]8.4 三元一次方程组
  5. 判断string是否为数字
  6. 智邦国际怎么样?企业管理软件好不好?
  7. 数据绑定以及Container.DataItem几种方式与用法分析 收藏
  8. 初识 RESTful API规范
  9. iOS与Opencv的探秘之Opencv认识,适配Xcode
  10. acwing 3 完全背包
  11. IOCP不可忽视的细节
  12. jquery选择器《-》
  13. oracle外部结合,浅谈Oracle外部文件
  14. python django ajax 逻辑推理_python django初识ajax
  15. 一些Python的惯用法和小技巧:Pythonic
  16. 利用MO实现流场显示
  17. VMP2.0版本带壳调试教程
  18. vrep和matlab,使用Matlab与V-REP联合仿真 - Play V-REP with Matlab
  19. 在小程序中使用百度地图
  20. 魔兽世界怀旧服哪个服务器金价稳定,魔兽世界怀旧服 金价到底会跌到多少的分析...

热门文章

  1. 【CCAI 2016】人工智能驱动的人机交互技术挑战和应用思路
  2. 算法与数据结构-DP算法及简单实例
  3. 谁说程序员不可以浪漫了,钢铁程序员也可以写情话
  4. 外网访问内网服务器设置方法(路由器设置)
  5. 2021-09-08 使用easyexcel解析几十万条数据时报错
  6. ConcurrentHashMap 能否保证绝对的线程安全?
  7. call线程起名字_多线程面试题总结
  8. 工程技术人员以计算机为辅助工具,计算机辅助设计与制造复习资料
  9. C语言-编写函数统计输入文本中单词的个数,单词之间用空格符、换行符、跳格符隔开,用@作为输入结束标志。
  10. linux拷贝目录并修改名字,linux复制文件夹、重命名文件夹、删除文件夹