TP5.0整合webuploader实现多图片上传功能
在https://github.com/fex-team/webuploader 下载webuploader并解压,
解压后放到public里面。其中我把解压缩后的文件夹改名为webuploader,放到了public/static/文件夹下。
将你放到public下的webuploader文件夹中的examples/imageupload/index.html复制到在对应需要文件上传功能的视图文件夹下面
将其中的css和js文件路径进行替换,ThinkPHP5.0中 __STATIC__直接指向了项目下的public/static文件下
下面这里的有点长,如果需要知道哪段是自己添加的 可搜索 ‘自己添加的’
这几个字,有注释的
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <title>WebUploader演示</title>
- <link rel="stylesheet" type="text/css" href="__STATIC__/webuploader/css/webuploader.css" />
- <link rel="stylesheet" type="text/css" href="__STATIC__/webuploader/examples/imageupload/style.css" />
- </head>
- <body>
- <!--这段form用于提交路径和其他表单信息 自己添加的-->
- <form action="{:url('gjourney/gjourney_add')}" method="post">
- <input type="hidden" id="image_url" name="image_url" />
- <input type="submit" value="提交">
- </form>
- <div id="wrapper">
- <div id="container">
- <!--头部,相册选择和格式选择-->
- <div id="uploader">
- <div class="queueList">
- <div id="dndArea" class="placeholder">
- <div id="filePicker"></div>
- <p>或将照片拖到这里,单次最多可选300张</p>
- </div>
- </div>
- <div class="statusBar" style="display:none;">
- <div class="progress">
- <span class="text">0%</span>
- <span class="percentage"></span>
- </div><div class="info"></div>
- <div class="btns">
- <div id="filePicker2"></div><div class="uploadBtn">开始上传</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <script type="text/javascript" src="__STATIC__/webuploader/examples/imageupload/jquery.js"></script>
- <script type="text/javascript" src="__STATIC__/webuploader/dist/webuploader.js"></script>
- <script>//**其实这一段js就是upload.js粘过来的,改成自己的路径**
- var imgurl = new Array();//这个是自己添加的,用于把多张图片的路径放到这个jQuery数组中然后赋值到表单提交
- (function( $ ){
- // 当domReady的时候开始初始化
- $(function() {
- var $wrap = $('#uploader'),
- // 图片容器
- $queue = $( '<ul class="filelist"></ul>' )
- .appendTo( $wrap.find( '.queueList' ) ),
- // 状态栏,包括进度和控制按钮
- $statusBar = $wrap.find( '.statusBar' ),
- // 文件总体选择信息。
- $info = $statusBar.find( '.info' ),
- // 上传按钮
- $upload = $wrap.find( '.uploadBtn' ),
- // 没选择文件之前的内容。
- $placeHolder = $wrap.find( '.placeholder' ),
- $progress = $statusBar.find( '.progress' ).hide(),
- // 添加的文件数量
- fileCount = 0,
- // 添加的文件总大小
- fileSize = 0,
- // 优化retina, 在retina下这个值是2
- ratio = window.devicePixelRatio || 1,
- // 缩略图大小
- thumbnailWidth = 110 * ratio,
- thumbnailHeight = 110 * ratio,
- // 可能有pedding, ready, uploading, confirm, done.
- state = 'pedding',
- // 所有文件的进度信息,key为file id
- percentages = {},
- // 判断浏览器是否支持图片的base64
- isSupportBase64 = ( function() {
- var data = new Image();
- var support = true;
- data.onload = data.onerror = function() {
- if( this.width != 1 || this.height != 1 ) {
- support = false;
- }
- }
- data.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
- return support;
- } )(),
- // 检测是否已经安装flash,检测flash的版本
- flashVersion = ( function() {
- var version;
- try {
- version = navigator.plugins[ 'Shockwave Flash' ];
- version = version.description;
- } catch ( ex ) {
- try {
- version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')
- .GetVariable('$version');
- } catch ( ex2 ) {
- version = '0.0';
- }
- }
- version = version.match( /\d+/g );
- return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );
- } )(),
- supportTransition = (function(){
- var s = document.createElement('p').style,
- r = 'transition' in s ||
- 'WebkitTransition' in s ||
- 'MozTransition' in s ||
- 'msTransition' in s ||
- 'OTransition' in s;
- s = null;
- return r;
- })(),
- // WebUploader实例
- uploader;
- if ( !WebUploader.Uploader.support('flash') && WebUploader.browser.ie ) {
- // flash 安装了但是版本过低。
- if (flashVersion) {
- (function(container) {
- window['expressinstallcallback'] = function( state ) {
- switch(state) {
- case 'Download.Cancelled':
- alert('您取消了更新!')
- break;
- case 'Download.Failed':
- alert('安装失败')
- break;
- default:
- alert('安装已成功,请刷新!');
- break;
- }
- delete window['expressinstallcallback'];
- };
- var swf = './expressInstall.swf';
- // insert flash object
- var html = '<object type="application/' +
- 'x-shockwave-flash" data="' + swf + '" ';
- if (WebUploader.browser.ie) {
- html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
- }
- html += 'width="100%" height="100%" style="outline:0">' +
- '<param name="movie" value="' + swf + '" />' +
- '<param name="wmode" value="transparent" />' +
- '<param name="allowscriptaccess" value="always" />' +
- '</object>';
- container.html(html);
- })($wrap);
- // 压根就没有安转。
- } else {
- $wrap.html('<a href="http://www.adobe.com/go/getflashplayer" target="_blank" border="0"><img alt="get flash player" src="http://www.adobe.com/macromedia/style_guide/images/160x41_Get_Flash_Player.jpg" /></a>');
- }
- return;
- } else if (!WebUploader.Uploader.support()) {
- alert( 'Web Uploader 不支持您的浏览器!');
- return;
- }
- // 实例化
- uploader = WebUploader.create({
- pick: {
- id: '#filePicker',
- label: '点击选择图片'
- },
- formData: {
- uid: 123
- },
- dnd: '#dndArea',
- paste: '#uploader',
- swf: '__STATIC__/webuploader/dist/Uploader.swf',//改成自己的路径
- chunked: false,
- chunkSize: 512 * 1024,
- server: "{:url('gjourney/imageupload')}",//自己后台文件上传的路径
- // runtimeOrder: 'flash',
- // accept: {
- // title: 'Images',
- // extensions: 'gif,jpg,jpeg,bmp,png',
- // mimeTypes: 'image/*'
- // },
- // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
- disableGlobalDnd: true,
- fileNumLimit: 300,
- fileSizeLimit: 200 * 1024 * 1024, // 200 M
- fileSingleSizeLimit: 50 * 1024 * 1024 // 50 M
- });
- // 拖拽时不接受 js, txt 文件。
- uploader.on( 'dndAccept', function( items ) {
- var denied = false,
- len = items.length,
- i = 0,
- // 修改js类型
- unAllowed = 'text/plain;application/javascript ';
- for ( ; i < len; i++ ) {
- // 如果在列表里面
- if ( ~unAllowed.indexOf( items[ i ].type ) ) {
- denied = true;
- break;
- }
- }
- return !denied;
- });
- uploader.on('dialogOpen', function() {
- console.log('here');
- });
- // uploader.on('filesQueued', function() {
- // uploader.sort(function( a, b ) {
- // if ( a.name < b.name )
- // return -1;
- // if ( a.name > b.name )
- // return 1;
- // return 0;
- // });
- // });
- // 添加“添加文件”的按钮,
- uploader.addButton({
- id: '#filePicker2',
- label: '继续添加'
- });
- uploader.on('ready', function() {
- window.uploader = uploader;
- });
- /**底下的uploadSuccess也是自己添加的,用来接收控制器返回的图片路径**/
- uploader.on('uploadSuccess',function(file,response){
- imgurl.push(response);//控制器返回多张图片路径追加到刚开始声明的imgurl数组中
- $("#image_url").val(imgurl);//然后赋给hidden表单
- // alert(imgurl);
- });
- // 当有文件添加进来时执行,负责view的创建
- function addFile( file ) {
- var $li = $( '<li id="' + file.id + '">' +
- '<p class="title">' + file.name + '</p>' +
- '<p class="imgWrap"></p>'+
- '<p class="progress"><span></span></p>' +
- '</li>' ),
- $btns = $('<div class="file-panel">' +
- '<span class="cancel">删除</span>' +
- '<span class="rotateRight">向右旋转</span>' +
- '<span class="rotateLeft">向左旋转</span></div>').appendTo( $li ),
- $prgress = $li.find('p.progress span'),
- $wrap = $li.find( 'p.imgWrap' ),
- $info = $('<p class="error"></p>'),
- showError = function( code ) {
- switch( code ) {
- case 'exceed_size':
- text = '文件大小超出';
- break;
- case 'interrupt':
- text = '上传暂停';
- break;
- default:
- text = '上传失败,请重试';
- break;
- }
- $info.text( text ).appendTo( $li );
- };
- if ( file.getStatus() === 'invalid' ) {
- showError( file.statusText );
- } else {
- // @todo lazyload
- $wrap.text( '预览中' );
- uploader.makeThumb( file, function( error, src ) {
- var img;
- if ( error ) {
- $wrap.text( '不能预览' );
- return;
- }
- if( isSupportBase64 ) {
- img = $('<img src="'+src+'">');
- $wrap.empty().append( img );
- } else {
- $.ajax('__STATIC__/webuploader/server/preview.php', {//这里的路径也改成自己自资源的路径
- method: 'POST',
- data: src,
- dataType:'json'
- }).done(function( response ) {
- if (response.result) {
- img = $('<img src="'+response.result+'">');
- $wrap.empty().append( img );
- } else {
- $wrap.text("预览出错");
- }
- });
- }
- }, thumbnailWidth, thumbnailHeight );
- percentages[ file.id ] = [ file.size, 0 ];
- file.rotation = 0;
- }
- file.on('statuschange', function( cur, prev ) {
- if ( prev === 'progress' ) {
- $prgress.hide().width(0);
- } else if ( prev === 'queued' ) {
- $li.off( 'mouseenter mouseleave' );
- $btns.remove();
- }
- // 成功
- if ( cur === 'error' || cur === 'invalid' ) {
- console.log( file.statusText );
- showError( file.statusText );
- percentages[ file.id ][ 1 ] = 1;
- } else if ( cur === 'interrupt' ) {
- showError( 'interrupt' );
- } else if ( cur === 'queued' ) {
- $info.remove();
- $prgress.css('display', 'block');
- percentages[ file.id ][ 1 ] = 0;
- } else if ( cur === 'progress' ) {
- $info.remove();
- $prgress.css('display', 'block');
- } else if ( cur === 'complete' ) {
- $prgress.hide().width(0);
- $li.append( '<span class="success"></span>' );
- }
- $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );
- });
- $li.on( 'mouseenter', function() {
- $btns.stop().animate({height: 30});
- });
- $li.on( 'mouseleave', function() {
- $btns.stop().animate({height: 0});
- });
- $btns.on( 'click', 'span', function() {
- var index = $(this).index(),
- deg;
- switch ( index ) {
- case 0:
- uploader.removeFile( file );
- return;
- case 1:
- file.rotation += 90;
- break;
- case 2:
- file.rotation -= 90;
- break;
- }
- if ( supportTransition ) {
- deg = 'rotate(' + file.rotation + 'deg)';
- $wrap.css({
- '-webkit-transform': deg,
- '-mos-transform': deg,
- '-o-transform': deg,
- 'transform': deg
- });
- } else {
- $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');
- // use jquery animate to rotation
- // $({
- // rotation: rotation
- // }).animate({
- // rotation: file.rotation
- // }, {
- // easing: 'linear',
- // step: function( now ) {
- // now = now * Math.PI / 180;
- // var cos = Math.cos( now ),
- // sin = Math.sin( now );
- // $wrap.css( 'filter', "progid:DXImageTransform.Microsoft.Matrix(M11=" + cos + ",M12=" + (-sin) + ",M21=" + sin + ",M22=" + cos + ",SizingMethod='auto expand')");
- // }
- // });
- }
- });
- $li.appendTo( $queue );
- }
- // 负责view的销毁
- function removeFile( file ) {
- var $li = $('#'+file.id);
- delete percentages[ file.id ];
- updateTotalProgress();
- $li.off().find('.file-panel').off().end().remove();
- }
- function updateTotalProgress() {
- var loaded = 0,
- total = 0,
- spans = $progress.children(),
- percent;
- $.each( percentages, function( k, v ) {
- total += v[ 0 ];
- loaded += v[ 0 ] * v[ 1 ];
- } );
- percent = total ? loaded / total : 0;
- spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' );
- spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' );
- updateStatus();
- }
- function updateStatus() {
- var text = '', stats;
- if ( state === 'ready' ) {
- text = '选中' + fileCount + '张图片,共' +
- WebUploader.formatSize( fileSize ) + '。';
- } else if ( state === 'confirm' ) {
- stats = uploader.getStats();
- if ( stats.uploadFailNum ) {
- text = '已成功上传' + stats.successNum+ '张照片至XX相册,'+
- stats.uploadFailNum + '张照片上传失败,<a class="retry" href="#">重新上传</a>失败图片或<a class="ignore" href="#">忽略</a>'
- }
- } else {
- stats = uploader.getStats();
- text = '共' + fileCount + '张(' +
- WebUploader.formatSize( fileSize ) +
- '),已上传' + stats.successNum + '张';
- if ( stats.uploadFailNum ) {
- text += ',失败' + stats.uploadFailNum + '张';
- }
- }
- $info.html( text );
- }
- function setState( val ) {
- var file, stats;
- if ( val === state ) {
- return;
- }
- $upload.removeClass( 'state-' + state );
- $upload.addClass( 'state-' + val );
- state = val;
- switch ( state ) {
- case 'pedding':
- $placeHolder.removeClass( 'element-invisible' );
- $queue.hide();
- $statusBar.addClass( 'element-invisible' );
- uploader.refresh();
- break;
- case 'ready':
- $placeHolder.addClass( 'element-invisible' );
- $( '#filePicker2' ).removeClass( 'element-invisible');
- $queue.show();
- $statusBar.removeClass('element-invisible');
- uploader.refresh();
- break;
- case 'uploading':
- $( '#filePicker2' ).addClass( 'element-invisible' );
- $progress.show();
- $upload.text( '暂停上传' );
- break;
- case 'paused':
- $progress.show();
- $upload.text( '继续上传' );
- break;
- case 'confirm':
- $progress.hide();
- $( '#filePicker2' ).removeClass( 'element-invisible' );
- $upload.text( '开始上传' );
- stats = uploader.getStats();
- if ( stats.successNum && !stats.uploadFailNum ) {
- setState( 'finish' );
- return;
- }
- break;
- case 'finish':
- stats = uploader.getStats();
- if ( stats.successNum ) {
- alert( '上传成功' );
- } else {
- // 没有成功的图片,重设
- state = 'done';
- location.reload();
- }
- break;
- }
- updateStatus();
- }
- uploader.onUploadProgress = function( file, percentage ) {
- var $li = $('#'+file.id),
- $percent = $li.find('.progress span');
- $percent.css( 'width', percentage * 100 + '%' );
- percentages[ file.id ][ 1 ] = percentage;
- updateTotalProgress();
- };
- uploader.onFileQueued = function( file ) {
- fileCount++;
- fileSize += file.size;
- if ( fileCount === 1 ) {
- $placeHolder.addClass( 'element-invisible' );
- $statusBar.show();
- }
- addFile( file );
- setState( 'ready' );
- updateTotalProgress();
- };
- uploader.onFileDequeued = function( file ) {
- fileCount--;
- fileSize -= file.size;
- if ( !fileCount ) {
- setState( 'pedding' );
- }
- removeFile( file );
- updateTotalProgress();
- };
- uploader.on( 'all', function( type ) {
- var stats;
- switch( type ) {
- case 'uploadFinished':
- setState( 'confirm' );
- break;
- case 'startUpload':
- setState( 'uploading' );
- break;
- case 'stopUpload':
- setState( 'paused' );
- break;
- }
- });
- uploader.onError = function( code ) {
- alert( 'Eroor: ' + code );
- };
- $upload.on('click', function() {
- if ( $(this).hasClass( 'disabled' ) ) {
- return false;
- }
- if ( state === 'ready' ) {
- uploader.upload();
- } else if ( state === 'paused' ) {
- uploader.upload();
- } else if ( state === 'uploading' ) {
- uploader.stop();
- }
- });
- $info.on( 'click', '.retry', function() {
- uploader.retry();
- } );
- $info.on( 'click', '.ignore', function() {
- alert( 'todo' );
- } );
- $upload.addClass( 'state-' + state );
- updateTotalProgress();
- });
- })( jQuery );
- </script>
- </body>
- </html>
如果直接引入的upload.js,而不是直接粘过来的话
就需要找到webuploader/examples/imageupload/upload.js文件,在第154行,或者搜索server,将后台地址改为你想要的地址(其实就是指的文件上传的方法的地址),我的改成了’imgupload’ 注意经过我多次试验,’{:url(“”)}’助手函数不会被解析,这里不能使用。
效果:
文件上传的后台方法
将ThinkPHP5文档中关于图片上传的代码写进去,将请求的名称改成file。
- public function imgupload()
- {
- $file = request()->file('file');
- // 移动到框架应用根目录/public/uploads/ 目录下
- $info = $file->move(ROOT_PATH . 'public' . DS . 'uploads');
- if($info){
- // 成功上传后 获取上传信息
- // 输出 jpg
- $data['path']=str_replace('\\',"/","/uploads/".$info->getSaveName());
- return json_encode($data['path']);//把路径ajax用json方式返回到视图中
- }else{
- // 上传失败获取错误信息
- echo $file->getError();
- }
- }
具体上传到那个文件夹、上传大小类型后缀的验证、文件的命名规则等,根据自己需要进行书写。注意这里虽然是多图上传,但上传时候的循环已经被插件封装好了,不需要我们使用多图上传中的循环方式进行上传。
上传界面如下
提交了,打印出来的路径
要改这个插件的大小和位置的话在style.css里的#wrapper里margin的属性值和witch的属性值,具体大小自己调。
TP5.0整合webuploader实现多图片上传功能的更多相关文章
- SpringMVC:学习笔记(10)——整合Ckeditor且实现图片上传
SpringMVC:学习笔记(10)——整合Ckeditor且实现图片上传 配置CKEDITOR 精简文件 解压之后可以看到ckeditor/lang下面有很多语言的js,如果不需要那么多种语言的,可 ...
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(七)图片上传功能
日常啰嗦 前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合>讲了富文本编辑器UEditor的整合与使用 ...
- Thinkphp整合阿里云OSS图片上传实例
Thinkphp3.2整合阿里云OSS图片上传实例,图片上传至OSS可减少服务器压力,节省宽带,安全又稳定,阿里云OSS对于做负载均衡非常方便,不用传到各个服务器了 首先引入阿里云OSS类库 < ...
- SpringBoot整合Fastdfs,实现图片上传(IDEA)
我们部署Fastdfs,就是为了实现文件的上传. 现在使用idea整合Fastdfs,实现图片上传 部署环境:Centos7部署分布式文件存储(Fastdfs) 利用Java客户端调用FastDFS ...
- thinkphp达到UploadFile.class.php图片上传功能
片上传在站点里是非经常常使用的功能.ThinkPHP里也有自带的图片上传类(UploadFile.class.php) 和图片模型类(Image.class.php).方便于我们去实现图片上传功能,以 ...
- PHP语言学习之php做图片上传功能
本文主要向大家介绍了PHP语言学习之php做图片上传功能,通过具体的内容向大家展示,希望对大家学习php语言有所帮助. 今天来做一个图片上传功能的插件,首先做一个html文件:text.php < ...
- [Ting's笔记Day8]活用套件carrierwave gem:(3)Deploy图片上传功能到Heroku网站
前情提要: 身为Ruby新手村民,创造稳定且持续的学习步调很重要,我用的方法就是一周在IT邦写三篇笔记,希望藉由把笔记和遇到的bug记录下来的过程,能帮助到未来想用Ruby on Rails架站的新手 ...
- H5 利用vue实现图片上传功能。
H5的上传图片如何实现呢? 以下是我用vue实现的图片上传功能,仅供参考. <!DOCTYPE html> <html> <head> <meta chars ...
- vue 图片上传功能
这次做了vue页面的图片上传功能,不带裁剪功能的! 首先是html代码,在input框上添加change事件,如下: <ul class="clearfix"> ...
随机推荐
- LG1983 「NOIP2013」车站分级 拓扑排序
问题描述 LG1983 题解 考虑建立有向边\((a,b)\),代表\(a\)比\(b\)低级. 于是枚举每一辆车次经过的车站\(x \in [l,r]\),如果不是车辆停靠的车站,则从\(x\)向每 ...
- Autofac注册组件详解
注册概念:我们通过创建 ContainerBuilder 来注册 组件 并且告诉容器哪些 组件 暴露了哪些 服务.组件 可以通过 反射 创建; 通过提供现成的 实例创建; 或者通过 lambda 表达 ...
- 毕业一年的大专生程序员工作总结(java后台)
文章导读 一.回眸过去-- 闲扯的话-- 零碎的技术 二.经验总结-- 沟通交流-- 贵在坚持-- 合理规划 三.展望未来-- 积累行业背景-- 学习清单 四.最后补充 一. 回牟过去 1.闲扯的话 ...
- Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4) 题解
Happy Birthday, Polycarp! Make Them Odd As Simple as One and Two Let's Play the Words? Two Fairs Bea ...
- CSP2019 树的重心 题解
本题当然可以通过大力讨论每棵子树的size的大小关系,然后用各种数据结构暴力维护.但是我更倾向于用一种更为性质的做法. 首先讲一下我在考场上想到的做法(没写).就是考虑换根,在换根的过程中计算每一条边 ...
- [清华集训2017]小 Y 和地铁(神奇思路,搜索,剪枝,树状数组)
世界上最不缺的就是好题. 首先考虑暴搜.(还有什么题是从这东西推到正解的……) 首先单独一个换乘站明显没用,只用考虑一对对的换乘站. 那么有八种情况:(从题解偷图) 然后大力枚举每个换 ...
- [LeetCode] 767. Reorganize String 重构字符串
Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...
- Python __name__的使用
__name__是什么 * __开头代表是系统变量; * __name__ 是标识模块名字的系统变量. 当前模块是主模块时, 模块名就是"__main__"; 当模块是被调用(im ...
- Python连载28-logging设置&logger解析
一.logging模块讲解 1.函数:logging.basicConfig() 参数讲解: (1)level代表高于或者等于这个值时,那么我们才会记录这条日志 (2)filename代表日志会写在这 ...
- Vue2 实践揭秘 错误列表
京东上的购买地址 作者是土生土长的聪明中国人 https://item.jd.com/12176536.html 64页 const bookID = this.$router.params.id 搞 ...