H5学习之路-图片上传(cropper、webuploader)

好久没有写博客了,感觉都不习惯了。一方面是因为工作占用的时间过多,另一方面是自己有点懒,没有坚持。好了,少扯这些没用的东西,直入主题呗。

笔者目前在公司会接触到H5的开发,也就是手机端app的开发,但是用的H5,而非原生的方式,主要是节省开发时间,不必针对android或者ios各自单独开发一套。但是,H5的方式因为各个系统、不同版本之间也会存在一些兼容性的问题,所以选择一些合适的插件,也是至关重要,特别是兼容性方面的处理。

图片上传,这个功能相信很多童鞋都会用到,但是在手机端就得注意一些兼容性的问题,比如在ios上就存在图片旋转的bug,再就是要考虑图片的压缩、裁剪、旋转、 等问题。今天,笔者就给大家介绍两个插件cropper和webuploader。cropper是一款使用简单且功能强大的图片剪裁jQuery插件。该图片剪裁插件支持图片放大缩小,支持图片旋转,支持触摸屏设备,支持canvas,并且支持跨浏览器使用。而WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。如果你的H5项目是基于zepto.js,你就可以使用webuploader这个插件;如果你的H5项目是基于jquery,你就可以使用cropper这个插件。webuploader是兼容zepto和jquery的,而cropper只能基于jquery。

下面,提供下这两个插件的学习地址:

一、插件目录结构介绍

笔者这个例子的目录结构以及所需插件,截图如下:
这里写图片描述

二、cropper图片上传

页面imageUpload1.html:

<!DOCTYPE html>
<html>
<head>
  <title>cropper图片上传</title>
  <meta charset="utf-8"/>
  <link rel="stylesheet" href="/m/plugins/cropper/cropper.min.css" />
</head>
<body>

<input id="btn1" type="file" accept="image/*,camera" capture="camera" style="opacity: 0;"/>

<div>
  <button id="upload_btn" >上传头像</button>
  <button id="image_save" >保存</button> 
  <img id="face_image" style="width:50px;height:50px;border-radius: 25px;border: 1px solid #fff;"/>
</div>

<div class="upload-img" style="width:100%;height: 100%;">
  <img src=""/>
</div>

<script src="/m/plugins/jquery/jquery-1.12.2.js" type="text/javascript"></script>
<script src="/m/plugins/cropper/cropper.min.js" type="text/javascript"></script>
<script src="/m/plugins/cropper/canvas-toBlob.js" type="text/javascript"></script>
<script src="../../scripts/imageUpload/imageUpload1.js" type="text/javascript"></script>
</body>
</html>

js imageUpload1.js:

/**
 * cropper图片上传
 */
$(function() {
  console.log('cropper图片上传。。。');

  //触发input file
  $('#upload_btn').click(function() {
    console.log('模拟点击。。。');
    $('#btn1').trigger('click');
  });

  //图片上传
  var $image = $('.upload-img > img');
  $image.cropper({
      viewMode: 1,
//      preview: '.img-preview', //不同尺寸预览区
      aspectRatio: 1, //裁剪比例,NaN-自由选择区域
      autoCropArea: 0.7, //初始裁剪区域占图片比例
      crop: function(data) { //裁剪操作回调
      }
  });
  var fileName; //选择上传的文件名
  $('#btn1').change(function(){
      var file = this.files[0];
      fileName = file.name;
      var reader = new FileReader();
      //reader回调,重新初始裁剪区
      reader.onload = function(){
          // 通过 reader.result 来访问生成的 DataURL
          var url = reader.result;
          //选择图片后重新初始裁剪区
          $image.cropper('reset', true).cropper('replace', url);
      };
      reader.readAsDataURL(file);
  });

  /*
   * 上传图片
   */
  $('#image_save').click(function() {
      var type = $image.attr('src').split(';')[0].split(':')[1];

      var canVas = $image.cropper("getCroppedCanvas", {});
      //将裁剪的图片加载到face_image
      $('#face_image').attr('src', canVas.toDataURL());
      canVas.toBlob(function(blob) {
          var formData = new FormData();
          formData.append("file", blob, fileName);

          $.ajax({
              type: "POST",
              url: '/sys/file/uploadImage.do',
              data: formData,
              contentType: false, //必须
              processData: false, //必须
              dataType: "json",
              success: function(retJson){
                  //清空上传文件的值
                  $('#btn1').val('');

                  //上传成功
                  console.log('retJson:', retJson);
              },
              error : function() {
                  //清空上传文件的值
                  $(_pageId + '#btn1').val('');
              }
          });
      }, type);
  });

  //取消
  $("#image_cancel").click(function() {
    //清空上传文件的值
    $(_pageId + inputFileId).val('');
  });
});

效果图如下:
这里写图片描述

三、WebUploader图片上传

页面imageUpload2.html:

<!DOCTYPE html>
<html>
<head>
  <title>webuploader图片上传</title>
  <meta charset="utf-8"/>
  <link rel="stylesheet" href="/m/plugins/webuploder/webuploader.css" />
</head>
<body>

<img id="face_image" style="width:50px;height:50px;border-radius: 25px;border: 1px solid #fff;"/>

<div id="uploader-demo">
  <div id="fileList" class="uploader-list"></div>
  <div id="filePicker">选择图片</div>
</div>

<script src="/m/plugins/zepto/zepto.min.js" type="text/javascript"></script>
<script src="/m/plugins/webuploder/webuploader.html5only.min.js" type="text/javascript"></script>
<script src="../../scripts/imageUpload/imageUpload2.js" type="text/javascript"></script>
</body>
</html>

js imageUpload2.js:

/**
 * webuploader图片上传
 */
$(function() {
  console.log('webuploader图片上传。。。');

  var webuploaderutil = {};
  // Web Uploader实例
  var uploader;

  var $list = $('#fileList'),
  // 优化retina, 在retina下这个值是2
  ratio = window.devicePixelRatio || 1,
  thumbnailWidth = 100 * ratio, thumbnailHeight = 100 * ratio,

  // 初始化Web Uploader
  uploader = WebUploader.create({
    // 自动上传。
    auto : true,
    // 文件接收服务端。
    server : '/sys/file/uploadImage.do',
    // 选择文件的按钮。可选。
    // 内部根据当前运行是创建,可能是input元素,也可能是flash.
    pick : '#filePicker',
    // 只允许选择文件,可选。
    accept : {
      title : 'Images',
      extensions : 'gif,jpg,jpeg,bmp,png',
      mimeTypes : 'image/*'
    }
  });

  // 当有文件添加进来的时候
  uploader.on('fileQueued', function(file) {
     var $li = $('<div id="' + file.id + '" class="file-item thumbnail">'
        + '<img>' + '<div class="info">' + file.name + '</div>'
        + '</div>'), $img = $li.find('img');

     $list.append($li);

    // 创建缩略图
    uploader.makeThumb(file, function(error, src) {
      if (error) {
        $("#face_image").replaceWith('<span>不能预览</span>');
        $img.attr( 'src', src );
        return;
      }

      $img.attr( 'src', src );
      $("#face_image").attr('src', src);
    }, thumbnailWidth, thumbnailHeight);

  });

  // 文件上传过程中创建进度条实时显示。
  uploader.on('uploadProgress', function(file, percentage) {
    var $li = $( '#'+file.id ),
    $percent = $li.find('.progress span');

    // 避免重复创建
    if ( !$percent.length ) {
        $percent = $('<p class="progress"><span></span></p>')
                .appendTo( $li )
                .find('span');
    }

    $percent.css( 'width', percentage * 100 + '%' );
  });

  // 文件上传成功,给item添加成功class, 用样式标记上传成功。
  uploader.on('uploadSuccess', function(file, response) {
    $('#' + file.id).addClass('upload-state-done');

    //重新初始化
//    webuploaderutil.uploadPicByResp(uploadDiv, imgEle, success, error);
    console.log('response:', response);
  });

  // 文件上传失败,现实上传出错。
  uploader.on('uploadError', function(file) {
    var $li = $('#' + file.id), $error = $li.find('div.error');

    // 避免重复创建
    if (!$error.length) {
      $error = $('<div class="error"></div>').appendTo($li);
    }

    $error.text('上传失败');
  });

  // 完成上传完了,成功或者失败,先删除进度条。
  uploader.on('uploadComplete', function(file) {
    $('#' + file.id).find('.progress').remove();
  });
});

效果图如下:
这里写图片描述

四、后台sevlet请求图片处理

因为笔者搭的是springMVC的框架,所以提供的代码写法就是SpringMVC的写法,大家也可以用sevlet,这个没什么区别,代码如下:

/**
 * Project Name:qyk_testSpringMVC
 * File Name:FileController.java
 * Package Name:com.qiyongkang.sys.controller
 * Date:2016年11月6日下午3:12:05
 * Copyright (c) 2016, Thinkive(http://www.thinkive.com/) All Rights Reserved.
 *
*/

package com.qiyongkang.sys.controller;

import java.io.File;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.qiyongkang.sys.dto.ExtJsObject;

/**
 * ClassName:FileController <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON. <br/>
 * Date: 2016年11月6日 下午3:12:05 <br/>
 * 
 * @author qiyongkang
 * @version
 * @since JDK 1.6
 * @see
 */
@Controller
@RequestMapping
public class FileController {
    /**
     * 日志类
     */
    private static Logger log = LogManager.getLogger(FileController.class);

    private String tempPath = "/uploadImageTemp";// 临时存储目录

    private String savePath = "/userImage";// 存储目录

    private String fileName = ""; // 文件名

    @RequestMapping
    @ResponseBody
    public ExtJsObject uploadImage(HttpServletRequest request) {
        ExtJsObject extJsObject = new ExtJsObject();
        try {
            // 获取临时目录
            String tempPathDir = request.getSession().getServletContext().getRealPath(this.tempPath);
            File tempPathDirFile = new File(tempPathDir);
            if (!tempPathDirFile.exists()) {
                tempPathDirFile.mkdirs();
            }

            // 存储目录
            String realDir = request.getSession().getServletContext().getRealPath(this.savePath);
            File realDirFile = new File(realDir);
            if (!realDirFile.exists()) {
                realDirFile.mkdirs();
            }

            // Create a factory for disk-based file items
            DiskFileItemFactory factory = new DiskFileItemFactory();

            // Set factory constraints
            factory.setSizeThreshold(4096); // 设置缓冲区大小,这里是4kb
            factory.setRepository(tempPathDirFile);// 设置缓冲区目录

            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);

            // Set overall request size constraint
            upload.setSizeMax(4194304); // 设置最大文件尺寸,这里是4MB

            List<FileItem> items = upload.parseRequest(request);// 得到所有的文件
            Iterator<FileItem> i = items.iterator();
            if (i.hasNext()) {
                FileItem fi = (FileItem) i.next();
                String fileName = fi.getName();
                if (fileName != null) {
                    // 这里加一个限制,如果不是图片格式,则提示错误. (gif,jpg,jpeg,bmp,png)
                    String suffixName = FilenameUtils.getExtension(fileName);
                    if ("gif".equalsIgnoreCase(suffixName) || "jpg".equalsIgnoreCase(suffixName)
                            || "jpeg".equalsIgnoreCase(suffixName) || "bmp".equalsIgnoreCase(suffixName)
                            || "png".equalsIgnoreCase(suffixName)) {
                        // 文件名
                        this.fileName = new Date().getTime() + "." + FilenameUtils.getExtension(fileName);
                        File savedFile = new File(realDir, this.fileName);
                        fi.write(savedFile);
                        // 小图片
                        File savedSmallFile = new File(realDir + "/small/", this.fileName);
                        FileUtils.copyFile(savedFile, savedSmallFile);
                    } else {
                        extJsObject.setSuccess(false);
                        extJsObject.setMsg("非图片格式,请重新上传!");
                    }
                }
            }

            extJsObject.setSuccess(true);
            extJsObject.setMsg("上传成功!");
            extJsObject.setResult(this.fileName);
        } catch (Exception e) {
            extJsObject.setSuccess(false);
            extJsObject.setMsg("上传失败!");
            log.error("图片上传失败", e);
        }
        return extJsObject;
    }
}

好了,就讲到这儿了,至于页面显示的问题,大家可以作一些显示、隐藏或者样式的调整,希望给大家带来帮助!

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值