js压缩图片(ajax、form提交)(pc、mobile测试ok)(Java)
1. 目的:
上传先进行图片压缩,然后再把压缩后的图片上传到服务器。
2. 思路:
上传前用js对图片压缩,把利用canvas生成的base64字符串,传入后台,(无所谓ajax或者form,同时也可以解决图片无刷新上传),在Java后台将获取到的base64字符串输出为图片,即可。
3. 代码:
引用mobileBUGFix.mini.js(移动端的补丁)
<!DOCTYPE>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>上传前js压缩图片(ajax、form提交)(pc、mobile测试ok)(Java)</title>
</head>
<script type="text/javascript" src="jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="mobileBUGFix.mini.js"></script>
<script type="text/javascript">
var pre;//源图片名称
/**
* 获得base64
* @param {Object} obj
* @param {Number} [obj.width] 图片需要压缩的宽度,高度会跟随调整
* @param {Number} [obj.quality=0.8] 压缩质量,不压缩为1
* @param {Function} [obj.before(this, blob, file)] 处理前函数,this指向的是input:file
* @param {Function} obj.success(obj) 处理后函数
*
*/
$.fn.localResizeIMG = function(obj) {
this.on('change', function() {
var file = this.files[0];
pre = file.name;
var URL = window.URL || window.webkitURL;
var blob = URL.createObjectURL(file);
// 执行前函数
if ($.isFunction(obj.before)) {
obj.before(this, blob, file);
}
_create(blob, file);
this.value = ''; // 清空临时数据
});
/**
* 生成base64
* @param blob 通过file获得的二进制
*/
function _create(blob) {
var img = new Image();
img.src = blob;
img.onload = function() {
var that = this;
//生成比例
var w = that.width, h = that.height, scale = w / h;
w = obj.width || w;
h = w / scale;
//生成canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
$(canvas).attr({
width : w,
height : h
});
ctx.drawImage(that, 0, 0, w, h);
/**
* 生成base64
* 兼容修复移动设备需要引入mobileBUGFix.js
*/
var base64 = canvas.toDataURL('image/jpeg', obj.quality || 0.8);
// 修复IOS
if (navigator.userAgent.match(/iphone/i)) {
var mpImg = new MegaPixImage(img);
mpImg.render(canvas, {
maxWidth : w,
maxHeight : h,
quality : obj.quality || 0.8
});
base64 = canvas.toDataURL('image/jpeg', obj.quality || 0.8);
}
// 修复android
if (navigator.userAgent.match(/Android/i)) {
var encoder = new JPEGEncoder();
base64 = encoder.encode(ctx.getImageData(0, 0, w, h),
obj.quality * 100 || 80);
}
// 生成结果
var result = {
base64 : base64,
clearBase64 : base64.substr(base64.indexOf(',') + 1)
};
// 执行后函数
obj.success(result);
};
}
};
$(function() {
$("input[type=file]").each(function() {
var _this = $(this);
_this.localResizeIMG({
width : 400,
quality : 0.001,
success : function(result) {
//获取后缀名
var att = pre.substr(pre.lastIndexOf("."));
//压缩后图片的base64字符串
var base64_string = result.clearBase64;
//图片预览
var imgObj = $("#img");
imgObj.attr("src", "data:image/jpeg;base64," + base64_string) .show();
//拼接data字符串,传递会后台
var fileData = $("#fileData");
fileData.val(att + "," + imgObj.attr("src"));
//此处可直接使用ajax上传,也可存于form,表单提交上传
//此处例子使用ajax提交
$.ajax({
type : "POST",
url : "<%=request.getContextPath()%>/doUploadImg",
data :{
imgData : fileData.val()
},
dataType : "json",
success : function(msg){
alert(msg);
}
});
}
});
});
});
</script>
<body>
<p>上传前js压缩图片(ajax、form提交)(pc、mobile测试ok)(Java)</p>
选择文件:
<input id="file" class="form-control" type="file" accept="image/*" name="file1">
<img id="img" name="img" width="200" height="100" style="display: none;" />
<input type="text" id="fileData" name="fileData" />
</body>
</html>
4. localResizeIMG参数:
width:缩略图宽度
quality:图片质量,0—1,越大越好
localResizeIMG返回值
5. localResizeIMG使用:
result.base64:
带图片类型的base64编码,可直接用于img标签的src,如"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/…2wBDAAYEBQYFBAY”;
result.clearBase64:
不带图片类型的编码,如“/9j/4AAQSkZJRgABAQAAAQABAAD/…2wBDAAYEBQYFBAY”
$(document).ready(function(e) {
$('input:file').localResizeIMG({
width: 400,
quality: 1,
success: function (result) {
var base64_string = result.clearBase64,
}
});
});
6. 保存文件
在上面一步中,我们把base64_string 通过ajax传入到doUploadImg中,接下来我们就要在doUploadImg中接收base64参数,把它转换成img文件保存来服务器中,并给出提示。
package cn.gluepudding.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
@WebServlet("/doUploadImg")
public class DoUploadImg extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
// 获取参数
String imgData = request.getParameter("imgData");
// 绝对路径
String path = request.getSession().getServletContext().getRealPath("upload");
File targetFile = new File(path);
if (!targetFile.exists()) {
targetFile.mkdirs();
}
// 生成新的图片名称(入库)
String imgSuffix = imgData.split(",")[0];
String fileName = UUID.randomUUID().toString().replaceAll("-", "") + imgSuffix;
boolean flag = GenerateImage(imgData.split(",")[2], fileName, path);
out.print(flag);
out.flush();
out.close();
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
// 将base64字符文件输出图像
public static boolean GenerateImage(String imgStr, String fileName, String path) {
// 对字节数组字符串进行Base64解码并生成图片
if (imgStr == null) // 图像数据为空
return false;
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] b = decoder.decodeBuffer(imgStr);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {// 调整异常数据
b[i] += 256;
}
}
// 生成jpeg图片
String imgFilePath = path + "\\" + fileName;// 新生成的图片
OutputStream out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// 图片转化成base64字符串
public static String GetImageStr() {
// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
String imgFile = "d://test.jpg";// 待处理的图片
InputStream in = null;
byte[] data = null;
// 读取图片字节数组
try {
in = new FileInputStream(imgFile);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);// 返回Base64编码过的字节数组字符串
}
}
7. 不足之处:
当图片宽度小于localResizeIMG设置的width参数时,图片会被拉申,从而引起图片失真(比如width高为600,图片只在400px时,压缩后的图片就变成了600px,图片尺寸变大了,会失真)。
8. Demo下载
http://pan.baidu.com/s/1o68area
参考资料
http://www.cnblogs.com/manongxiaobing/p/4720568.html
http://blog.csdn.net/hfhwfw/article/details/5544408