基于html5和jquery的文件上传组件

发布于,归属于javascript5个座位已被强势霸占! 共有938人围观    


本文介绍一个采用HTML5 API的web应用—上传中心(Upload Center),允许用户从本地计算机中拖拽图片到浏览器窗口上传图片。有图片预览和上传进度条,这些都可由客户端来控制。上传后,这些图片只是被存储到服务器上了,接下来就可以随意引用了。

什么是HTML5 文件上传
上传文件运用了HTML5的三个新特性:1、新的文件读取api(File Reader API) 2、新的拖拽api(Drag & Drop API) 3、新的IO-ajax(增加了二进制数据传输)。下面是HTML5文件上传的步骤:

  1. 1、用户从本地计选择一个或多个文件拖拽到浏览器窗口。支持拖拽的的浏览器会触发一个事件,事件包括一些有用的信息,其中包涵被选中的文件信息。
  2. 2、用HTML5的文件读取api,以二进制数据读取被选文件,并存储到内存中。
  3. 3、用XMLHttpRequest对象的新方法-sendAsBinary,将数据传到服务器。

jQuery插件— Filedrop已经封装好这些功能,并且提供配置接口来限制上传文件的大小和指定回调函数。非常方便运用到自己的应用中。
目前来看,文件上传只能在firefox和chrome浏览器中使用,但其他主流浏览器的下个版本已经计划支持该功能了。当然对于不支持的浏览器可以简单的放置input file控件来代替。但本文重点是应用HTML5上,这里就不做处理了。

现在开始,首先是HTML结构

上传中心的Html结构比较简单。先声明HTML5的doctype,然后引入样式文件和脚本文件-script.js、filedrop插件脚本和jquery库。
html结构如下:
index.html

  1. <!DOCTYPE html>
  2.     <html>
  3.         <head>
  4.             <meta charset="utf-8" />
  5.             <title>HTML5 File Drag and Drop Upload with jQuery and PHP | Tutorialzine Demo</title>
  6.     
  7.             <!-- Our CSS stylesheet file -->
  8.             <link rel="stylesheet" href="assets/css/styles.css" />
  9.     
  10.             <!--[if lt IE 9]>
  11.               <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  12.             <![endif]-->
  13.         </head>
  14.     
  15.         <body>
  16.     
  17.             <header>
  18.                 <h1>HTML5 File Upload with jQuery and PHP</h1>
  19.             </header>
  20.     
  21.             <div id="dropbox">
  22.                 <span class="message">Drop images here to upload. <br /><i>(they will only be visible to you)</i></span>
  23.             </div>
  24.     
  25.             <!-- Including The jQuery Library -->
  26.             <script src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
  27.     
  28.             <!-- Including the HTML5 Uploader plugin -->
  29.             <script src="assets/js/jquery.filedrop.js"></script>
  30.     
  31.             <!-- The main script file -->
  32.             <script src="assets/js/script.js"></script>
  33.     
  34.         </body>
  35.     </html>

这里div#dropbox会传递给filedrop插件,插件会监听是否有文件被拖拽到div#dropbox上。当上传出错时,展现信息的span会提示错误信息。(如,浏览器不支持HTML5的api时就会显示相应的提示信息)

然后,文件选择后,通过基于jquery的js编码实现图片预览效果。预览html结构如下:

  1. <div class="preview done">
  2.     
  3.         <span class="imageHolder">
  4.             <img src="" />
  5.             <span class="uploaded"></span>
  6.         </span>
  7.     
  8.         <div class="progressHolder">
  9.             <div class="progress"></div>
  10.         </div>
  11.     
  12.     </div>

本段包括图片预览(img 的src属性会用图片的DataURL填充)和上传进度条的html结构。预览容器的一个class值done,可以使span.uploaded显示(默认情况下该span是隐藏的)。该span用绿色背景标记,表示上传已完成。

html结构完成了,接下来开始脚本编码。
事实上文件上传相关的功能Filedrop插件都封装好了,这里的上传中心只需要运用它,并且将回调的方法传递给它。需要在服务器端写一段php脚本来处理上传的文件,下面一节会讲到。
第一步,写一个辅助的方法来读取文件对象(该对象是文件被选择后由浏览器端创建的,包括如文件名称、文件路劲和文件大小等的属性),然后生成预览的html结构。
assets/js/script.js

  1. var template = '<div class="preview">'+
  2.                             '<span class="imageHolder">'+
  3.                                 '<img />'+
  4.                                 '<span class="uploaded"></span>'+
  5.                             '</span>'+
  6.                             '<div class="progressHolder">'+
  7.                                 '<div class="progress"></div>'+
  8.                             '</div>'+
  9.                         '</div>';
  10.     
  11.         function createImage(file){
  12.     
  13.             var preview = $(template),
  14.                 image = $('img', preview);
  15.     
  16.             var reader = new FileReader();
  17.     
  18.             image.width = 100;
  19.             image.height = 100;
  20.     
  21.             reader.onload = function(e){
  22.     
  23.                 // e.target.result holds the DataURL which
  24.                 // can be used as a source of the image:
  25.     
  26.                 image.attr('src',e.target.result);
  27.             };
  28.     
  29.             // Reading the file as a DataURL. When finished,
  30.             // this will trigger the onload function above:
  31.             reader.readAsDataURL(file);
  32.     
  33.             message.hide();
  34.             preview.appendTo(dropbox);
  35.             // Associating a preview container
  36.             // with the file, using jQuery's $.data():
  37.     
  38.             $.data(file,preview);
  39.         }

Template用于创建图片预览的HTML结构。获取图片的DataURL(64位编码的图片数据),然后赋值给图片的src。然后创建好的预览会被添加到div#dropbox中。现在还剩下filedrop的回调处理了。
assets/js/script.js

  1. $(function(){
  2.     
  3.         var dropbox = $('#dropbox'),
  4.             message = $('.message', dropbox);
  5.     
  6.         dropbox.filedrop({
  7.             // The name of the $_FILES entry:
  8.             paramname:'pic',
  9.     
  10.             maxfiles: 5,
  11.             maxfilesize: 2, // in mb
  12.             url: 'post_file.php',
  13.     
  14.             uploadFinished:function(i,file,response){
  15.                 $.data(file).addClass('done');
  16.                 // response is the JSON object that post_file.php returns
  17.             },
  18.     
  19.             error: function(err, file) {
  20.                 switch(err) {
  21.                     case 'BrowserNotSupported':
  22.                         showMessage('Your browser does not support HTML5 file uploads!');
  23.                         break;
  24.                     case 'TooManyFiles':
  25.                         alert('Too many files! Please select 5 at most!');
  26.                         break;
  27.                     case 'FileTooLarge':
  28.                         alert(file.name+' is too large! Please upload files up to 2mb.');
  29.                         break;
  30.                     default:
  31.                         break;
  32.                 }
  33.             },
  34.     
  35.             // Called before each upload is started
  36.             beforeEach: function(file){
  37.                 if(!file.type.match(/^image\//)){
  38.                     alert('Only images are allowed!');
  39.     
  40.                     // Returning false will cause the
  41.                     // file to be rejected
  42.                     return false;
  43.                 }
  44.             },
  45.     
  46.             uploadStarted:function(i, file, len){
  47.                 createImage(file);
  48.             },
  49.     
  50.             progressUpdated: function(i, file, progress) {
  51.                 $.data(file).find('.progress').width(progress);
  52.             }
  53.     
  54.         });
  55.     
  56.         var template = '...';
  57.     
  58.         function createImage(file){
  59.             // ... see above ...
  60.         }
  61.     
  62.         function showMessage(msg){
  63.             message.html(msg);
  64.         }
  65.     
  66.     });

然后,被拖拽到div#dropbox的有效的图片文件通过post_file.php上传到服务器上。

PHP 处理:

在php服务器端,正常上传的图片和被拖拽上传的图片不会有区别。这意味着在服务器端只需要提供一个回调来处理上传的文件。
post_file.php

  1. // If you want to ignore the uploaded files,
  2.     // set $demo_mode to true;
  3.     
  4.     $demo_mode = false;
  5.     $upload_dir = 'uploads/';
  6.     $allowed_ext = array('jpg','jpeg','png','gif');
  7.     
  8.     if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
  9.         exit_status('Error! Wrong HTTP method!');
  10.     }
  11.     
  12.     if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){
  13.     
  14.         $pic = $_FILES['pic'];
  15.     
  16.         if(!in_array(get_extension($pic['name']),$allowed_ext)){
  17.             exit_status('Only '.implode(',',$allowed_ext).' files are allowed!');
  18.         } 
  19.     
  20.         if($demo_mode){
  21.     
  22.             // File uploads are ignored. We only log them.
  23.     
  24.             $line = implode('       ', array( date('r'), $_SERVER['REMOTE_ADDR'],$pic['size'], $pic['name']));
  25.             file_put_contents('log.txt', $line.PHP_EOL, FILE_APPEND);
  26.     
  27.             exit_status('Uploads are ignored in demo mode.');
  28.         }
  29.     
  30.         // Move the uploaded file from the temporary
  31.         // directory to the uploads folder:
  32.     
  33.         if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
  34.             exit_status('File was uploaded successfuly!');
  35.         }
  36.     
  37.     }
  38.     
  39.     exit_status('Something went wrong with your upload!');
  40.     
  41.     // Helper functions
  42.     
  43.     function exit_status($str){
  44.         echo json_encode(array('status'=>$str));
  45.         exit;
  46.     }
  47.     
  48.     function get_extension($file_name){
  49.         $ext = explode('.', $file_name);
  50.         $ext = array_pop($ext);
  51.         return strtolower($ext);
  52.     }

该段脚本执行监听http请求和验证上传的文件。(如果php脚本中不使用move_upload_file()方法上传文件,那么文件将自动在请求结束后予以删除。)

最后,给上传中心添加样式。

下面列出部分样式,一些与上传不相关的没有这里没有列出来。如果想看完整的样式,可以查看style.css
assets/css/styles.css

  1. /*-------------------------
  2.         Dropbox Element
  3.     --------------------------*/
  4.     
  5.     #dropbox{
  6.         background:url('../img/background_tile_3.jpg');
  7.     
  8.         border-radius:3px;
  9.         position: relative;
  10.         margin:80px auto 90px;
  11.         min-height: 290px;
  12.         overflow: hidden;
  13.         padding-bottom: 40px;
  14.         width: 990px;
  15.     
  16.         box-shadow:0 0 4px rgba(0,0,0,0.3) inset,0 -3px 2px rgba(0,0,0,0.1);
  17.     }
  18.     
  19.     #dropbox .message{
  20.         font-size: 11px;
  21.         text-align: center;
  22.         padding-top:160px;
  23.         display: block;
  24.     }
  25.     
  26.     #dropbox .message i{
  27.         color:#ccc;
  28.         font-size:10px;
  29.     }
  30.     
  31.     #dropbox:before{
  32.         border-radius:3px 3px 0 0;
  33.     }
  34.     
  35.     /*-------------------------
  36.         Image Previews
  37.     --------------------------*/
  38.     
  39.     #dropbox .preview{
  40.         width:245px;
  41.             height: 215px;
  42.         float:left;
  43.         margin: 55px 0 0 60px;
  44.         position: relative;
  45.         text-align: center;
  46.     }
  47.     
  48.     #dropbox .preview img{
  49.         max-width: 240px;
  50.         max-height:180px;
  51.         border:3px solid #fff;
  52.         display: block;
  53.     
  54.         box-shadow:0 0 2px #000;
  55.     }
  56.     
  57.     #dropbox .imageHolder{
  58.         display: inline-block;
  59.         position:relative;
  60.     }
  61.     
  62.     #dropbox .uploaded{
  63.         position: absolute;
  64.         top:0;
  65.         left:0;
  66.         height:100%;
  67.         width:100%;
  68.         background: url('../img/done.png') no-repeat center centerrgba(255,255,255,0.5);
  69.         display: none;
  70.     }
  71.     
  72.     #dropbox .preview.done .uploaded{
  73.         display: block;
  74.     }
  75.     
  76.     /*-------------------------
  77.         Progress Bars
  78.     --------------------------*/
  79.     
  80.     #dropbox .progressHolder{
  81.         position: absolute;
  82.         background-color:#252f38;
  83.         height:12px;
  84.         width:100%;
  85.         left:0;
  86.         bottom: 0;
  87.     
  88.         box-shadow:0 0 2px #000;
  89.     }
  90.     
  91.     #dropbox .progress{
  92.         background-color:#2586d0;
  93.         position: absolute;
  94.         height:100%;
  95.         left:0;
  96.         width:0;
  97.     
  98.         box-shadow: 0 0 1px rgba(255, 255, 255, 0.4) inset;
  99.     
  100.         -moz-transition:0.25s;
  101.         -webkit-transition:0.25s;
  102.             -o-transition:0.25s;
  103.         transition:0.25s;
  104.     }
  105.     
  106.     #dropbox .preview.done .progress{
  107.         width:100% !important;
  108.     }

Div.progress绝对定位。改变它的width(百分数值)来做进度条的显示。这里可以应用jquery实现动画效果。
到这里,HTML5的上传中心完成了。可以将它运用到文件上传服务、html5画廊、文件管理或别的新应用中。记得留下你的建议和意见!

本文翻译自《HTML5 File Uploads with jQuery》Demo演示

(如果您喜欢这篇教程,可以通过支付宝打赏我们1元哦,拜谢!)

感谢阅读,有问题请指出^^

辛勤码教程中...求订阅...O(∩_∩)O

跟作者说两句

:wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-? :) :( :!: 8-O 8)

5个座位已被强势霸占!

  1. 明河

    :wink: :wink: 坐个沙发,飞绿同学翻译这篇文章,非常用心哦,教程内容也非常棒。

  2. xthsky

    顶下 :twisted: 留着备用

  3. gyrate

    createImage()函数中如果reader.onload 失败会如何呢

  4. wmtimes

    效果很不错。但不是太会用。

  5. 雨蓝蓝

    好牛B的效果