开发环境
Windows 10 + Eclipse 4.5.2 + jdk 1.7.0 + Tomcat 8.0
用到的技术:struts2.3.35 + JSON工具包 + jQuery + ajaxfileupload.js (jQuery文件上传插件) + layer.js(弹出层插件)
ajaxfileupload 插件使用参数说明
1、url 上传处理程序地址。
2,fileElementId 需要上传的文件域的ID,即<input type="file">的ID。
3,secureuri 是否启用安全提交,默认为false。
4,dataType 服务器返回的数据类型。可以为xml,script,json,html。如果不填写,jQuery会自动判断。
5,success 提交成功后自动执行的处理函数,参数data就是服务器返回的数据。
6,error 提交失败自动执行的处理函数。
7,data 自定义参数。这个东西比较有用,当有数据是与上传的图片相关的时候,这个东西就要用到了。
8, type 当要提交自定义参数时,这个参数要设置成post
struts2异步上传文件
1. 首先使用 eclipse开发工具 创建Java Web项目 并且命名为 “FileUpload” ,添加相关的jar文件,struts.xml,配置web.xml
注意项目中还有layer.js插件要加。
2. 项目中添加文件上传控制器类(UploadAction.java)
package com.demo.action;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import net.sf.json.JSONObject;
public class UploadAction extends ActionSupport{
private File file1;//定义上传文件变量
private String file1FileName;//定义上传文件名变量
// 定义允许上传的文件扩展名
public static final String[] imageFileTypes = new String[] {".png",".jpg",".bmp",".gif"};
public static final float UPLOAD_FILE_SIZE = 10240.0f;//文件大小限制为 10 M
public static final String UPLOAD_FILE_DIR = "/upload/";//上传文件存放目录
//计算文件的大小(kb)
public static final float getLongSize(long longsize){
float size = 0.0F;
if (longsize > 1024){
size = longsize / 1024.0F;
}else{
size = 1024 / 1024.0F;
}
DecimalFormat format = new DecimalFormat("##.##");
return Float.parseFloat(format.format(size));
}
//格式化文件名(图片,word,txt等)
public String generateFileName(String fileName) {
DateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String formatDate = format.format(new Date());
int position = fileName.lastIndexOf(".");
String extension = fileName.substring(position).toLowerCase();
return formatDate + extension;
}
//异步上传文件
public String upload() throws Exception {
try {
/**
* 也可以使用这种方式获取上传的文件 ,后台如果不定义文件变量时
MultiPartRequestWrapper req = (MultiPartRequestWrapper) getRequest();
File[] files = req.getFiles("file");
if (files != null && files.length > 0){
//1 判断图片格式
//2 判断图片大小是否超出限制
String fileName = req.getFileNames("file")[0];
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
File file = files[0];
然后再这里判断文件类型,及大小是否超出限制
}
*/
Map<String, String> jsonMap = new HashMap<String, String>();
float filesize = 0.0f;
if (file1 != null) {
//获取上传文件名称,并得到文件的扩展名(转小写)
String fileName = getFile1FileName();
String fileExt = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
if (!Arrays.asList(imageFileTypes).contains(fileExt)) {
//获取文件失败,错误提示
jsonMap.put("status", "error");
jsonMap.put("message", "文件格式必须是png,jpg,bmp,gif其中一种!");
return ajaxJson(jsonMap);
}
//获得上传文件的大小,判断是否超出系统限制。
filesize = getLongSize(file1.length());
if (filesize >= UPLOAD_FILE_SIZE) {
jsonMap.put("status", "error");
jsonMap.put("message", "文件大小超过系统限制(10 M),请重试!");
return ajaxJson(jsonMap);
}
String newfilename = generateFileName(fileName);
String filePath = UPLOAD_FILE_DIR + newfilename;
File realFile = new File(ServletActionContext.getServletContext().getRealPath(filePath));
FileUtils.copyFile(file1, realFile);
if (file1.exists() && (!file1.isDirectory())) {
jsonMap.put("status", "success");
jsonMap.put("url", newfilename);
} else {
jsonMap.put("status", "error");
jsonMap.put("message", "文件上传失败,请重试!");
}
}
return ajaxJson(jsonMap);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("上传文件异常,请联系管理员!");
}
}
// 根据Map输出JSON,返回null
public String ajaxJson(Map<String, String> jsonMap) {
JSONObject jsonObject = JSONObject.fromObject(jsonMap);
return ajax(jsonObject.toString(), "text/html");
}
// AJAX输出,返回null
public String ajax(String content, String type) {
try {
HttpServletResponse response = ServletActionContext.getResponse();
response.setCharacterEncoding("UTF-8");
response.setContentType(type + ";charset=UTF-8");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.getWriter().println(content);
response.getWriter().flush();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public File getFile1() {
return file1;
}
public void setFile1(File file1) {
this.file1 = file1;
}
public String getFile1FileName() {
return file1FileName;
}
public void setFile1FileName(String file1FileName) {
this.file1FileName = file1FileName;
}
}
3. 新建测试页面upload1.jsp代码(WebContent 目录下):
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>1.普通文件上传例子</title>
</head>
<body>
<h3>1.普通文件上传例子</h3>
<form action="<%=basePath %>/upload.action" method="post" enctype="multipart/form-data">
<input type="file" name="file1" id="file1" />
<input id="uploadBtn1" type="button" value="上传" />
</form>
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/ajaxfileupload.js"></script>
<script type="text/javascript" src="js/layer/layer.js"></script>
<script type="text/javascript">
$(document).ready(
function(){
$("#uploadBtn1").click(function(){
var selectFile = $("#file1").val();
if (selectFile){
//指定上传文件域ID,表单文件域的name参数值(对应于后台定义的File对象)
var fileAreaId = "file1";
$.ajaxFileUpload({
url:'upload.action',
secureuri:false,
fileElementId:fileAreaId,
dataType:'json',
success: function (data, status)
{
if (data.status=="success"){
layer.alert("上传成功!上传到服务器的文件名是: " + data.url);
}
else{
layer.alert(data.message);
}
},
error: function (data, status, e){
layer.alert("上传文件失败,请重试!");
}
});
}
else{
layer.alert("您还未选择文件!");
}
})
});
</script>
</body>
</html>
4. 演示效果如下图:
struts2异步上传文件(前端压缩图片上传)
这里使用的HTML5中FormData对象,封装数据并传入到后台。
这里我们项目中的控制器类中添加File对象,已经upload2方法,并添加一个测试页面upload2.jsp
1. struts.xml 文件添加如下代码:
<action name="upload2" class="com.demo.action.UploadAction" method="upload2">
<result name="success">success.jsp</result>
</action>
2. UploadAction 类添加File对象及fileName并提供get、set方法,上传文件方法
private File file2;//定义上传文件变量
private String file2FileName;//定义上传文件名变量
//异步上传文件(前端压缩上传文件)
public String upload2() throws Exception {
try {
/**
* 也可以使用这种方式获取上传的文件 ,后台如果不定义文件变量时
MultiPartRequestWrapper req = (MultiPartRequestWrapper) getRequest();
File[] files = req.getFiles("file");
if (files != null && files.length > 0){
//1 判断图片格式
//2 判断图片大小是否超出限制
String fileName = req.getFileNames("file")[0];
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
File file = files[0];
然后再这里判断文件类型,及大小是否超出限制
}
*/
Map<String, String> jsonMap = new HashMap<String, String>();
float filesize = 0.0f;
if (file2 != null) {
//获取上传文件名称,并得到文件的扩展名(转小写)
String fileName = getFile2FileName();
String fileExt = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
if (!Arrays.asList(imageFileTypes).contains(fileExt)) {
//获取文件失败,错误提示
jsonMap.put("status", "error");
jsonMap.put("message", "文件格式必须是png,jpg,bmp,gif其中一种!");
return ajaxJson(jsonMap);
}
//获得上传文件的大小,判断是否超出系统限制。
filesize = getLongSize(file2.length());
if (filesize >= UPLOAD_FILE_SIZE) {
jsonMap.put("status", "error");
jsonMap.put("message", "文件大小超过系统限制(10 M),请重试!");
return ajaxJson(jsonMap);
}
String newfilename = generateFileName(fileName);
String filePath = UPLOAD_FILE_DIR + newfilename;
File realFile = new File(ServletActionContext.getServletContext().getRealPath(filePath));
FileUtils.copyFile(file2, realFile);
if (file2.exists() && (!file2.isDirectory())) {
jsonMap.put("status", "success");
jsonMap.put("url", newfilename);
} else {
jsonMap.put("status", "error");
jsonMap.put("message", "文件上传失败,请重试!");
}
}
return ajaxJson(jsonMap);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("上传文件异常,请联系管理员!");
}
}
public File getFile2() {
return file2;
}
public void setFile2(File file2) {
this.file2 = file2;
}
public String getFile2FileName() {
return file2FileName;
}
public void setFile2FileName(String file2FileName) {
this.file2FileName = file2FileName;
}
3. 新建测试页面upload2.jsp代码(WebContent 目录下):
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>2.图片(前端压缩)上传例子</title>
</head>
<body>
<h3>2.图片(前端压缩)上传例子</h3>
<input type="file" name="file2" id="file2" />
<input id="uploadBtn2" type="button" value="上传" />
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/ajaxfileupload.js"></script>
<script type="text/javascript" src="js/layer/layer.js"></script>
<script type="text/javascript">
//通用ajax方法 post 请求json数据
function ajaxFileUpload(url, postData, callBack,isAsync,loadtxt) {
try {
if (isAsync == undefined)
isAsync = false;
var lid = 0;
if (isAsync) {
if (loadtxt == undefined)
loadtxt = "文件上传中,请稍后...";
lid = layer.msg(loadtxt, { icon: 16, shade: [0.1, '#fff'] ,time:90000});
}
$.ajax({
url: url,
type: "POST",
data: postData,
dataType: "json",
cache: false,
processData: false, // 告诉jQuery不要去处理发送的数据
contentType: false, // 告诉jQuery不要去设置Content-Type请求头
async: isAsync,
timeout: 20000,
success: function (data) {
callBack(data);
},
error: function (data, status, e) {
if (status=='timeout'){
layer.msg("上传失败,连接服务器超时!");
}
else{
layer.msg("上传失败,网络异常或系统错误!");
}
},
complete: function () {
if (isAsync) {
layer.close(lid);
}
}
});
} catch (e) {
layer.alert("上传失败,统异常,请联系管理员!");
}
}
/*
三个参数
file:一个是文件(类型是图片格式),
w:一个是文件压缩的后宽度,宽度越小,字节越小
objDiv:一个是容器或者回调函数
photoCompress()
*/
function photoCompress(file,w,objDiv){
var ready=new FileReader();
/*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
ready.readAsDataURL(file);
ready.onload=function(){
var re=this.result;
canvasDataURL(re,w,objDiv);
}
}
function canvasDataURL(path, obj, callback){
var img = new Image();
img.src = path;
img.onload = function(){
var that = this;
var scale = 1;
if(that.width > 1000 || that.height > 1000){
if(that.width > that.height){
scale = 1000 / that.width;
}else{
scale = 1000 / that.height;
}
}
var w = that.width*scale;
var h = that.height*scale; //计算等比缩小后图片宽高
/**
var w = that.width,h = that.height,scale = w / h;
w = obj.width || w;
h = obj.height || (w / scale);
*/
//var quality = 0.7; // 默认图片质量为0.7
var quality = 1;
//生成canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// 创建属性节点
var anw = document.createAttribute("width");
anw.nodeValue = w;
var anh = document.createAttribute("height");
anh.nodeValue = h;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
ctx.drawImage(that, 0, 0, w, h);
// 图像质量
if(obj.quality && obj.quality <= 1 && obj.quality > 0){
quality = obj.quality;
}
// quality值越小,所绘制出的图像越模糊
var base64 = canvas.toDataURL('image/jpeg', quality);
// 回调函数返回base64的值
callback(base64);
}
}
/**
* 将以base64的图片url数据转换为Blob
* @param urlData
* 用url方式表示的base64图片数据
*/
function convertBase64UrlToBlob(urlData){
var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
function uploadFile2(selectFile){
// js 获取文件对象 跟 $("#file2") 一样
var fileObj = document.getElementById("file2").files[0];
// 得到上传文件的扩展名
var selectFileExtension = selectFile.substring(selectFile.lastIndexOf("."));
// 接收上传文件的后台地址
var url = "upload2.action";
var form = new FormData(); // FormData 对象
//大于1M,进行压缩上传
if(fileObj.size/1024 > 1025) {
photoCompress(fileObj, {
quality: 0.2
}, function(base64Codes){
var bl = convertBase64UrlToBlob(base64Codes);
//指定上传文件域,相当于页面表单文件域的name参数值(对应于后台定义的File对象))
form.append("file2", bl, "file_"+Date.parse(new Date()) + selectFileExtension);
ajaxFileUpload(
url,
form,
function(data){
if(data.status="success") {
layer.alert("上传成功!压缩并上传到服务器的文件名是: " + data.url);
}else{
layer.alert(data.message);
}
},
true
);
});
}else{
//小于等于1M 原图上传
//指定上传文件域,相当于页面表单文件域的name参数值(对应于后台定义的File对象))
form.append("file2", fileObj); // 文件对象
ajaxFileUpload(
url,
form,
function(data){
if(data.status="success") {
layer.alert("上传成功!压缩并上传到服务器的文件名是: " + data.url);
}else{
layer.alert(data.message);
}
},
true
);
}
}
$(document).ready(
function(){
$("#uploadBtn2").click(function(){
var selectFile = $("#file2").val();
if (selectFile){
uploadFile2(selectFile);
}
else{
layer.alert("您还未选择文件!");
}
})
});
</script>
</body>
</html>
4. 演示效果如下图:
最后可以对比一下,原图是4K高清图片,大小7M多,压缩后才几十K了
struts2异步上传文件(后端压缩图片上传)
这里还是继续使用ajaxfileupload插件上传,跟第一个例子一样,就是后台需要对文件进行压缩处理后再上传到服务器中。
1. struts.xml 文件添加如下代码:
<action name="upload3" class="com.demo.action.UploadAction" method="upload3">
<result name="success">success.jsp</result>
</action>
2. UploadAction类添加File对象及fileName并提供get、set方法,(压缩)上传文件方法
private File file3;//定义上传文件变量
private String file3FileName;//定义上传文件名变量
//异步上传文件(服务器压缩)
public String upload3() throws Exception {
try {
/**
* 也可以使用这种方式获取上传的文件 ,后台如果不定义文件变量时
MultiPartRequestWrapper req = (MultiPartRequestWrapper) getRequest();
File[] files = req.getFiles("file");
if (files != null && files.length > 0){
//1 判断图片格式
//2 判断图片大小是否超出限制
String fileName = req.getFileNames("file")[0];
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
File file = files[0];
然后再这里判断文件类型,及大小是否超出限制
}
*/
Map<String, String> jsonMap = new HashMap<String, String>();
float filesize = 0.0f;
if (file3 != null) {
//获取上传文件名称,并得到文件的扩展名(转小写)
String fileName = getFile3FileName();
String fileExt = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
if (!Arrays.asList(imageFileTypes).contains(fileExt)) {
//获取文件失败,错误提示
jsonMap.put("status", "error");
jsonMap.put("message", "文件格式必须是png,jpg,bmp,gif其中一种!");
return ajaxJson(jsonMap);
}
//获得上传文件的大小,判断是否超出系统限制。
filesize = getLongSize(file3.length());
if (filesize >= UPLOAD_FILE_SIZE) {
jsonMap.put("status", "error");
jsonMap.put("message", "文件大小超过系统限制(10 M),请重试!");
return ajaxJson(jsonMap);
}
String newfilename = generateFileName(fileName);
String filePath = UPLOAD_FILE_DIR + newfilename;
File realFile = new File(ServletActionContext.getServletContext().getRealPath(filePath));
/**这里不在使用copyFile直接上传了,因为要对文件进行压缩处理再上传
//FileUtils.copyFile(file1, realFile);
if (file1.exists() && (!file1.isDirectory())) {
jsonMap.put("status", "success");
jsonMap.put("url", newfilename);
} else {
jsonMap.put("status", "error");
jsonMap.put("message", "文件上传失败,请重试!");
}
*/
// 删除已经存在文件,重新压缩
if (realFile.exists() && (!realFile.isDirectory())) {
realFile.delete();
}
// 压缩文件上传逻辑 compressImage
boolean hasUploaded = compressImage(file3, realFile);
if (hasUploaded) {
jsonMap.put("status", "success");
jsonMap.put("url", newfilename);
} else {
jsonMap.put("status", "error");
jsonMap.put("message", "文件上传失败,请重试!");
}
}
return ajaxJson(jsonMap);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("上传文件异常,请联系管理员!");
}
}
/** 压缩图片文件再上传 */
private Boolean compressImage(File source_file,File target_file) throws Exception {
int maxWidth = 1000;//限制最大宽
int maxHeight = 1000;//限制最大高
//获得文件源
// InputStream ins = new FileInputStream(source_file);
// File file = new File(source_file.getOriginalFilename());
// inputStreamToFile(ins, file);
Image img = ImageIO.read(source_file);
int originWidth = img.getWidth(null);
int originHeight = img.getHeight(null);
int targetWidth = 0;//目标宽
int targetHeight = 0;//目标高
//宽或者高超过最大上限时进行压缩
if (originWidth > maxWidth || originHeight > maxHeight) {
if(originWidth >= originHeight){//横图或方图
targetWidth = maxWidth;
targetHeight = (int) Math.round(maxWidth * (double)originHeight / (double)originWidth);
}else{//竖图
targetHeight = maxHeight;
targetWidth = (int) Math.round(maxHeight * (double)originWidth / (double)originHeight);
}
}
else
{
targetWidth = originWidth;
targetHeight = originHeight;
}
System.out.println("压缩后图片大小: width="+targetWidth+" height="+targetHeight);
BufferedImage tag = new BufferedImage(targetWidth,targetHeight,BufferedImage.TYPE_INT_RGB);
tag.getGraphics().drawImage(img,0,0,targetWidth,targetHeight,null);
FileOutputStream out = new FileOutputStream(target_file);
//JPEGImageEncoder可适用于其他图片的类型的转换
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam encoder_param = JPEGCodec.getDefaultJPEGEncodeParam(tag);
encoder_param.setQuality(1f, true);//质量压缩,范围为0.1-1之间,若压缩尺寸过小,建议压缩质量设为最高1f
encoder.setJPEGEncodeParam(encoder_param);
encoder.encode(tag);
out.close();
return true;
}
public File getFile3() {
return file3;
}
public void setFile3(File file3) {
this.file3 = file3;
}
public String getFile3FileName() {
return file3FileName;
}
public void setFile3FileName(String file3FileName) {
this.file3FileName = file3FileName;
}
3. 新建测试页面upload3.jsp代码(WebContent 目录下):
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>3.图片(后端压缩)上传例子</title>
</head>
<body>
<h3>3.图片(后端压缩)上传例子</h3>
<form action="<%=basePath %>/upload3.action" method="post" enctype="multipart/form-data">
<input type="file" name="file3" id="file3" />
<input id="uploadBtn3" type="button" value="上传" />
</form>
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/ajaxfileupload.js"></script>
<script type="text/javascript" src="js/layer/layer.js"></script>
<script type="text/javascript">
$(document).ready(
function(){
$("#uploadBtn3").click(function(){
var selectFile = $("#file3").val();
if (selectFile){
//指定上传文件域,相当于页面表单文件域的name参数值(对应于后台定义的File对象)
var fileAreaId = "file3";
$.ajaxFileUpload({
url:'upload3.action',
secureuri:false,
fileElementId:fileAreaId,
dataType:'json',
success: function (data, status)
{
if (data.status=="success"){
layer.alert("上传成功!上传到服务器的文件名是: " + data.url);
}
else{
layer.alert(data.message);
}
},
error: function (data, status, e){
layer.alert("上传文件失败,请重试!");
}
});
}
else{
layer.alert("您还未选择文件!");
}
})
});
</script>
</body>
</html>
4. 演示效果如下图:
最后可以对比一下,原图是4K高清图片,大小7M多,压缩后才几百K了
ajaxFileUpload资料: ajaxFileUpload的使用和参数说明