jquery-file-upload angualrJS下使用简介

1.什么是jquery-file-upload

jQuery File Upload是一个非常优秀的上传组件,主要使用了XHR作为上传方式,并且利用了相当多的现代浏览器功能,所以可以实现诸如批量上传、超大文件上传、图片预览、拖拽上传、上传进度显示、跨域上传等功能。

美中不足的是jQuery File Upload的默认UI比较复杂,集成了全部功能,让jQuery File Upload的定制变得比较繁琐。同时jquery-file-upload官网上对angualrjs集成没有相关的API,doc 使得jquery-file-upload在angualrjs中难度极为复杂,网上关于相关集成的文章少之又少,故在此介绍。

 2.jquery-file-upload 与angualrJs 集成效果图

jquery-file-upload angualrJS下使用简介_第1张图片 批量上传

jquery-file-upload angualrJS下使用简介_第2张图片拖拽上传

jquery-file-upload angualrJS下使用简介_第3张图片进度条

jquery-file-upload angualrJS下使用简介_第4张图片

影集预览

jquery-file-upload angualrJS下使用简介_第5张图片

自动播放功能


3.相关实现

1.需要的js库

query-file-upload 方面

jquery-file-upload angualrJS下使用简介_第6张图片

预览效果依赖blueimp 的 gallery库 相关资源如下:

jquery-file-upload angualrJS下使用简介_第7张图片

为了预览效果的实现还需要load-image.all.min.js和canvas-to-blob.min.js这两个js 可以从网上下载

相关资源整合: http://pan.baidu.com/s/1slN6Jox

2.在app中引入相关js css


在app中引入相关module

jquery-file-upload angualrJS下使用简介_第8张图片

3.html的编写

<div >
    <h1>文件上传</h1>
    <!-- The file upload form used as target for the file upload widget -->
        <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">注意事项</h3>
        </div>
        <div class="panel-body">
            <ul>
                <li>单个图片上传大小限制为<strong>999 KB</strong> (default file size is unlimited).</li>
                <li>前选择对应格式的图片上传 (<strong>JPG, GIF, PNG</strong>)</li>
           </ul>
        </div>
    </div>
    <form id="fileupload"
    	 method="POST" 
    	 data-ng-controller="uploadController";
    	 enctype="multipart/form-data" 
    	 data-file-upload="options" 
    	 data-ng-class="{'fileupload-processing': processing() || loadingFiles}">
        <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
        <div class="row fileupload-buttonbar">
            <div class="col-lg-5">
                <!-- The fileinput-button span is used to style the file input field as button -->
                <span class="btn btn-success fileinput-button" ng-class="{disabled: disabled}">
                    <i class="glyphicon glyphicon-plus"></i>
                    <span>添加附件</span>
                    <input type="file" name="files[]" ng-show="options.maxNumberOfFiles==1" ng-disabled="disabled">
                    <input type="file" name="files[]" multiple ng-show="!options.maxNumberOfFiles" ng-disabled="disabled">
                </span>
                <button type="button" class="btn btn-primary start" data-ng-click="submit()">
                    <i class="glyphicon glyphicon-upload"></i>
                    <span>全部开始</span>
                </button>
                <button type="button" class="btn btn-danger cancel" data-ng-click="destoryAll()">
                    <i class="glyphicon glyphicon glyphicon-trash"></i>
                    <span>全部删除</span> 
                </button>
               
                <!-- The global file processing state -->
                <span class="fileupload-process"></span>
            </div>
            <!-- The global progress state -->
            <div class="col-lg-4 fade" data-ng-class="{in: active()}">
                <!-- The global progress bar -->
                <div class="progress progress-striped active" data-file-upload-progress="progress()"><div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"></div></div>
                <!-- The extended global progress state -->
                <div class="progress-extended"> </div>
            </div>
            <div class="col-lg-3">
            	 <button type="button" class="btn btn-warning" ng-click="cancelUpload()" style="float:right">
		                        <i class="glyphicon glyphicon-ban-circle"></i>
		                        <span>取消</span>
		        </button>
		    	<button type="button" class="btn btn-info" ng-click="saveUpload()" ng-disabled="saveStatus" style="float:right;margin-right:5px">
		                        <i class="glyphicon glyphicon-save"></i>
		                        <span>保存</span>
		        </button>
            </div>
        </div>
        <!-- The table listing the files available for upload/download -->
        <table class="table table-striped files ng-cloak">
            <tr data-ng-repeat="file in queue" data-ng-class="{'processing': file.$processing()}">
                <td data-ng-switch data-on="!!file.thumbnailUrl">
                    <div class="preview" data-ng-switch-when="true">
                        <a data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}" data-gallery>
                        	<img data-ng-src="{{file.thumbnailUrl}}" alt="" width="80" height="80">
                        </a>
                    </div>
                    <div class="preview" data-ng-switch-default data-file-upload-preview="file"></div>
                </td>
                <td>
                    <p class="name" data-ng-switch data-on="!!file.url">
                        <span data-ng-switch-when="true" data-ng-switch data-on="!!file.thumbnailUrl">
                            <a data-ng-switch-when="true" data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}" data-gallery>{{file.name}}</a>
                            <a data-ng-switch-default data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}">{{file.name}}</a>
                        </span>
                        <span data-ng-switch-default>{{file.name}}</span>
                    </p>
                    <strong data-ng-show="file.error" class="error text-danger">{{file.error}}</strong>
                </td>
                <td>
                    <p class="size">{{file.size | formatFileSize}}</p>
                    <div class="progress progress-striped active fade" data-ng-class="{pending: 'in'}[file.$state()]" data-file-upload-progress="file.$progress()"><div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"></div></div>
                </td>
                <td style="text-align:right">
                    <button type="button" class="btn btn-primary start" data-ng-click="file.$submit()" data-ng-hide="!file.$submit || options.autoUpload || file.status" data-ng-disabled="file.$state() == 'pending' || file.$state() == 'rejected'">
                        <i class="glyphicon glyphicon-upload"></i>
                        <span>开始</span>
                    </button>
                    <button type="button" class="btn btn-warning cancel" data-ng-click="file.$cancel()" data-ng-hide="!file.$cancel || file.status">
                        <i class="glyphicon glyphicon-ban-circle"></i>
                        <span>取消</span>
                    </button>
                    <button type="button" class="btn btn-danger destroy" ng-click="destory(file)" data-ng-hide="!file.status">
                        <i class="glyphicon glyphicon-trash"></i>
                        <span>删除</span>
                    </button>
                </td>
            </tr>
        </table>
        
    </form>
    <br>
</div>
<!-- The blueimp Gallery widget -->
<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even">
    <div class="slides"></div>
    <h3 class="title"></h3>
    <a class="prev">‹</a>
    <a class="next">›</a>
    <a class="close">×</a>
    <a class="play-pause"></a>
    <ol class="indicator"></ol>
</div>

4.controller的编写

var page=angular.module('upload.view',[]);

page.config(['$httpProvider', 'fileUploadProvider',
         function ($httpProvider, fileUploadProvider) {
             delete $httpProvider.defaults.headers.common['X-Requested-With'];
             fileUploadProvider.defaults.redirect = window.location.href.replace(
                 /\/[^\/]*$/,
                 '/cors/result.html?%s'
             );
             angular.extend(fileUploadProvider.defaults, {
                     disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent),
                     maxFileSize: 999000,
                     acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
                     maxNumberOfFiles :10    
             });
         }
     ]);
    page.controller('uploadController', [ '$scope', '$rootScope', '$http', 'RoleService', '$state', '$stateParams',
        '$window', function($scope, $rootScope, $http, RoleService, $state, $stateParams, $window) {
            var url =  '/servlet/UploadServlet';
            $scope.options = {
                url : url,
                dataType : 'json',
                autoUpload : false,
                acceptFileTypes : /(\.|\/)(gif|jpe?g|png)$/i,
                previewCrop : true,
                maxNumberOfFiles :1
            };
            $scope.queue=[];
            $scope.fileList=[];
            $scope.saveStatus=true;
            
            $scope.$on('fileuploadadd', function(event, data) {
                if($scope.options.maxNumberOfFiles==1){
                    $scope.queue=[];
                }
            });
            
            $scope.$on('fileuploaddone', function(event, data) {
                if(data.result.length==1){
                     var uploadSuccessName=data.result[0].name;
                     var uploadSuccessFileName=data.result[0].fileName;
                     var uploadSuccessStatus=data.result[0].status;
                     var uploadSuccessFileId=data.result[0].fileId;
                    for(var i=0;i<$scope.queue.length;i++){
                      if($scope.queue[i].name==uploadSuccessName){
                          $scope.queue[i].url="/servlet/DownLoadServlet?f="+uploadSuccessFileName;
                          $scope.queue[i].thumbnailUrl="/servlet/DownLoadServlet?f="+uploadSuccessFileName;   
                          $scope.queue[i].status=uploadSuccessStatus;   
                          $scope.queue[i].fileId=uploadSuccessFileId;
                          $scope.saveStatus=false;
                      }
                    }
                }
                for(var i=0;i<$scope.queue.length;i++){
                    if($scope.queue[i].status==1){
                        $scope.saveStatus=false;
                    }else{
                        $scope.saveStatus=true;
                        break;
                    }
                  }
            });
            
            $scope.destoryAll=function(){
                $scope.clear($scope.queue);
                
            }     
            
            $scope.saveUpload=function(){
                $scope.fileList=[];
                for(var i=0;i<$scope.queue.length;i++){
                    if($scope.queue[i].status){
                        $scope.fileList.push($scope.queue[i]);
                    }
                }
                $scope.closeThisDialog($scope.fileList);
            }
            
            $scope.cancelUpload=function(){
                $scope.closeThisDialog();
            }
     
            $scope.destory=function(file){
                $scope.clear(file);
            }
  }]);


客户端方面代码就此完成  下面是server端的代码

UploadServlet

   protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{
        // 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
        String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File file = new File(savePath);
        // 判断上传文件的保存目录是否存在
        if (!file.exists() && !file.isDirectory()) {
            System.out.println(savePath + "目录不存在,需要创建");
            // 创建目录
            file.mkdirs();
        }
        List<FileMeta> files = new LinkedList<FileMeta>();
        // 1. 使用Apache的FileUpload上传文件
        files.addAll(MultipartRequestHandler.getInstance().uploadByApacheFileUpload(request, savePath));
        // Remove some files
        while (files.size() > 20) {
            files.remove(0);
        }
        // 2.设置响应类型的JSON
        response.setContentType("application/json");
        // 3. 转换 List<FileMeta> 为 JSON 格式
        ObjectMapper mapper = new ObjectMapper();
        // 4. 发送结果到客户端
        mapper.writeValue(response.getOutputStream(), files);

    }
MultipartRequestHandler
 public  List<FileMeta> uploadByApacheFileUpload(HttpServletRequest request,String savePath) throws IOException, ServletException{
        List<FileMeta> files = new LinkedList<FileMeta>();
        // 1. 检查要求有多文件内容
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        FileMeta temp = null;
        // 2. If yes (it has multipart "files")
        if(isMultipart){
          // 2.1 Apache的FileUpload类实例化
          DiskFileItemFactory factory = new DiskFileItemFactory();
          factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
          ServletFileUpload upload = new ServletFileUpload(factory);
          upload.setHeaderEncoding("UTF-8"); 
          //设置上传单个文件的大小的最大值,目前是设置为1024*1024*5字节,也就是5MB
          upload.setFileSizeMax(1024*1024*5);
          //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为100MB
          upload.setSizeMax(1024*1024*100);
          // 2.2 解析请求
          try {
            // 2.3 得到所有上传FileItem
            List<FileItem> items = upload.parseRequest(request);
            // 2.4 遍历每一个FileItem
            for(FileItem item:items){
              // 2.5 如果FileItem不是文件类型 
                if (item.isFormField()) { 
                    
                } else {
                    // 2.7 创建filemeta对象
                    temp = new FileMeta();
                    temp.setContent(item.getInputStream());
                    temp.setFileType(item.getContentType());
                    temp.setSize(item.getSize()/1024+ "Kb");
                    saveFile(temp,item,savePath);
                    temp.setStatus("1");
                    String fileId=saveAttachment(temp);  //保存到数据库
                    temp.setFileId(fileId);
                    files.add(temp);
               }   
             }
          } catch (FileUploadException e) {
              e.printStackTrace();
          }
        }
        return files;
      }
      
      private  void saveFile(FileMeta temp,FileItem item,String savePath){
          String filename=item.getName();
          //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,
          //而有些只是单纯的文件名,如:1.txt
          filename = filename.substring(filename.lastIndexOf("\\")+1);
          temp.setName(filename);
          //得到上传文件的扩展名
//        String fileExtName = filename.substring(filename.lastIndexOf(".")+1);
          //得到文件保存的名称 UUID
          String saveFilename=makeFileName(filename);
          temp.setFileName(saveFilename);
          //得到文件的保存目录  hash打散
          String realSavePath = makePath(saveFilename, savePath);
          try {
              //获取item中的上传文件的输入流
              InputStream in = item.getInputStream();
              //创建一个文件输出流
              FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);
              //创建一个缓冲区
              byte buffer[] = new byte[1024];
              //判断输入流中的数据是否已经读完的标识
              int len = 0;
              //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
              while((len=in.read(buffer))>0){
                 //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
                 out.write(buffer, 0, len);
              }
              //关闭输入流  关闭输出流  删除处理文件上传时生成的临时文件
              in.close();
              out.flush();
              out.close();
              item.delete();
            } catch (Exception e) {
                temp.setError("上传失败,文件类型错误/超过上传大小限制");
                e.printStackTrace();
            } 
      }
     
      private String saveAttachment(FileMeta temp){
         Attachment attachment=new Attachment();
         attachment.setAttachmentId(temp.getFileName());
         attachment.setName(temp.getName());
         attachment.setFileType(temp.getFileType());
         attachment.setSize(temp.getSize());
         String id=attachmentService.saveAttachment(attachment);
         return id;
      }
    /**
     * @Method: makeFileName
     * @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
     */
    private static String makeFileName(String filename) { // 2.jpg
        // 为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
        return UUID.randomUUID().toString() + "_" + filename;
    }

    /**
     * 为防止一个目录下面出现太多文件,要使用hash算法打散存储
     */
    private static String makePath(String filename, String savePath) {
        // 得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
        int hashcode = filename.hashCode();
        int dir1 = hashcode & 0xf; // 0--15
        int dir2 = (hashcode & 0xf0) >> 4; // 0-15
        // 构造新的保存目录
        String dir = savePath + "\\" + dir1 + "\\" + dir2; // upload\2\3 upload\3\5
        // File既可以代表文件也可以代表目录
        File file = new File(dir);
        // 如果目录不存在
        if (!file.exists()) {
            // 创建目录
            file.mkdirs();
        }
        return dir;
    }
FileMeta
@JsonIgnoreProperties({"content"})
public class FileMeta {
    
    private String fileName;
    private String fileType;
    private String size;
    private String thumbnailUrl;
    private String url;
    private String name;
    private String error;
    private String status;
    private InputStream content;
    private String fileId;

    public String getFileId() {
        return fileId;
    }

    public void setFileId(String fileId) {
        this.fileId = fileId;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFileType() {
        return fileType;
    }

    public void setFileType(String fileType) {
        this.fileType = fileType;
    }

    public InputStream getContent() {
        return content;
    }

    public void setContent(InputStream content) {
        this.content = content;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public String getThumbnailUrl() {
        return thumbnailUrl;
    }

    public void setThumbnailUrl(String thumbnailUrl) {
        this.thumbnailUrl = thumbnailUrl;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

原理:上传成功后服务器需向客户端返回上传成功的files 方便jquery-file-upload进行解析 以此判断上传状态 进行下载 预览等后续操作

文件下载Servlet

package com.apusic.justice.wx.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 下载文件Servlet
 * 
 * @author zhaoyang
 * 
 */

public class DownLoadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 得到要下载的文件名
        request.setCharacterEncoding("UTF-8");
        String fileName = request.getParameter("f"); // 23239283-92489-QQ图片.jpg
        // 上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
        String fileSaveRootPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        // 通过文件名找出文件的所在目录
        String path = findFileSavePathByFileName(fileName, fileSaveRootPath);
        // 得到要下载的文件
        File file = new File(path + "\\" + fileName);
        // 如果文件不存在
        if (!file.exists()) {
            return;
        }
        // 处理文件名
        String realname = fileName.substring(fileName.indexOf("_") + 1);
        // 设置响应头,控制浏览器下载该文件
        response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
        // 读取要下载的文件,保存到文件输入流
        FileInputStream in = new FileInputStream(path + "\\" + fileName);
        // 创建输出流
        OutputStream out = response.getOutputStream();
        // 创建缓冲区
        byte buffer[] = new byte[1024];
        int len = 0;
        // 循环将输入流中的内容读取到缓冲区当中
        while ((len = in.read(buffer)) > 0) {
            // 输出缓冲区的内容到浏览器,实现文件下载
            out.write(buffer, 0, len);
        }
        // 关闭文件输入流
        in.close();
        // 关闭输出流
        out.close();
    }

    /**
     * @Method: findFileSavePathByFileName
     * @Description: 通过文件名和存储上传文件根目录找出要下载的文件的所在路径
     */
    public String findFileSavePathByFileName(String filename, String saveRootPath) {
        int hashcode = filename.hashCode();
        int dir1 = hashcode & 0xf; // 0--15
        int dir2 = (hashcode & 0xf0) >> 4; // 0-15
        String dir = saveRootPath + "\\" + dir1 + "\\" + dir2; // upload\2\3 upload\3\5
        File file = new File(dir);
        if (!file.exists()) {
            // 创建目录
            file.mkdirs();
        }
        return dir;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

web.xml

<servlet>
     <servlet-name>UploadServlet</servlet-name>
     <servlet-class>com.a_1.a_1.wx.util.UploadServlet</servlet-class>
 	</servlet>
	 <servlet-mapping>
	     <servlet-name>UploadServlet</servlet-name>
	     <url-pattern>/servlet/UploadServlet</url-pattern>
	 </servlet-mapping>   
	  
	<servlet>
	     <servlet-name>DownLoadServlet</servlet-name>
	     <servlet-class>com.a_1.a_1.wx.util.DownLoadServlet</servlet-class>
 	</servlet>
	 <servlet-mapping>
	     <servlet-name>DownLoadServlet</servlet-name>
	     <url-pattern>/servlet/DownLoadServlet</url-pattern>
	 </servlet-mapping> 


你可能感兴趣的:(AngularJS)