昨天下午搞一个功能要实现图片上传 ,感觉听起来挺简单 但是业务需要有点扯 就先写一个简单的功能在根据需求修改。
废话少说上图。
其实我实现的功能很少 现在安装要求完成工作需求无非就是最好的
下面我把我的工作要求写下来
前期我是用
sturts ajax fileupload
下面试一下整体的架构 和必须的要有的jar
实现的功能
这是前台代码
<%@ page language="java" import="java.util.*" 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"> <html> <head> <base href="<%=basePath%>"> <title>个人中心</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script> <script type="text/javascript" src="js/jquery.Jcrop.js"></script> <script type="text/javascript" src="js/ajaxfileupload.js"></script> <link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" /> <% response.setHeader("Pragma","No-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires", 0); %> <style type="text/css"> .pre{ position: absolute; left: 300px; top: 100px; z-index:999; width:100px; height:100px; overflow:hidden; margin-left:5px; } .after{ position: absolute; left: 600px; top: 40px; z-index:999; } .cropdiv{ //设置div固定大小 overflow : hidden; width : 180px; height : 180px; } </style> <script type="text/javascript"> $(function(){ $("#cropiconcontainer").Jcrop({ //定义回调函数 onSelect:showSelect, onChange:showChange, //设置属性 //bgColor:'black', //setSelect:[100,100,50,50], //bgOpacity: 4, aspectRatio: 1 }); }); //截取图片选定后执行的函数 function showSelect(c){ $("#showMessage").html(""); var s = "select: c.x=" + c.x + ",c.y=" + c.y + ",c.x2=" + c.x2 + ",c.y2=" + c.y2 + ",c.w=" + c.w + ",c.h=" + c.h; $("#showMessage").html(s); $('#x1').val(c.x); $('#y1').val(c.y); $('#x2').val(c.x2); $('#y2').val(c.y2); $('#width').val(c.w); $('#height').val(c.h); } //截取图片改变位置时执行的回调函数 function showChange(c){ $("#showMessage").html(""); var s = "change: c.x=" + c.x + ",c.y=" + c.y + ",c.x2=" + c.x2 + ",c.y2=" + c.y2 + ",c.w=" + c.w + ",c.h=" + c.h; $("#showMessage").html(s); //显示图像 var rx = 100 / c.w; var ry = 100 / c.h; $("#showPreview").css({ width : Math.round(rx * 180) + 'px', //180、180参数一般都要根据图片来设定 height : Math.round(ry * 180) + 'px', marginLeft : '-' + Math.round(rx * c.x) + 'px', marginTop : '-' + Math.round(ry * c.y) + 'px' }); } </script> <script type="text/javascript"> //用ajaxFileUpload组件进行图片上传操作 function uploadImage() { var name = document.getElementById("image").value; if(validateImage(name)) { var url = "uploadImage.action"; //var d = $("form1").serialize(); $.ajaxFileUpload({ url: url, //需要链接到服务器地址 secureuri:false, data:{ "x1" : $("#x1").val(), "y1" : $("#y1").val(), "x2" : $("#x2").val(), "y2" : $("#y2").val(), "width" : $("#width").val(), "height" : $("#height").val() }, //表单数据 fileElementId:"image", //文件选择框的id属性 dataType: 'json', //服务器返回的格式,可以是json success: function (data, status) { //相当于java中try语句块的用法 alert("上传图片成功!"); //alert(data.message); //alert(data.imagePath); $("#yourImage").attr("src",data.imagePath); }, error: function (data, status, e) { //相当于java中catch语句块的用法 alert("图片上传失败,请重新选择图片"); alert("状态:" + status); alert("异常信息:" + e); } }); } } //用ajaxFileUpload组件进行图片预览操作 function previewImage() { var name = document.getElementById("image").value; if(validateImage(name)) { var url = "previewImage.action"; $.ajaxFileUpload({ url: url, //需要链接到服务器地址 secureuri:false, fileElementId:"image", //文件选择框的id属性 dataType: 'json', //服务器返回的格式,可以是json success: function (data, status) { //相当于java中try语句块的用法 //[{isSuccess:true|false,serverPath:XXXXX}] //alert("上传图片成功!"); //alert(data.message); //alert(data.imagePath); $("#showImage").attr("src",data.imagePath); $("#showPreview").attr("src",data.imagePath); }, error: function (data, status, e) { //相当于java中catch语句块的用法 alert("图片预览失败,请重新选择图片"); alert("状态:" + status); alert("异常信息:" + e); } }); } } </script> </head> <body> <form id="form1" name="form1" method="post" action="" enctype="multipart/form-data"> <input type="file" id="image" name="image" onchange="previewImage();"> <input type="button" name="preview" value="预览" onclick="previewImage();"> <input type="button" name="upload" value="上传" onclick="uploadImage();"> <!-- 截取图片需要的参数用hidden域存放 --> <input id="x1" name="x1" type="hidden"> <input id="y1" name="y1" type="hidden"> <input id="x2" name="x2" type="hidden"> <input id="y2" name="y2" type="hidden"> <input id="width" name="width" type="hidden"> <input id="height" name="height" type="hidden"> </form> <br> <!-- 默认图片为images/1.jpg --> <!-- 预览整幅图片 --> <div id="cropiconcontainer" class="cropdiv"> <img alt="" src="images/1.jpg" id="showImage" name="showImage"> </div> <!-- 预览截取的图片 --> <div class="pre"> <span>截取预览:</span><br> <img alt="" src="images/1.jpg" id="showPreview"> </div> <div id="showMessage"></div> <!-- 查看已上传的图片 --> <div class="after"> <span>当前保存的图片:</span><br> <img alt="" src="images/1.jpg" id="yourImage"> </div> </body> </html>
struts2 配置文件 代码
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <constant name="struts.i18n.encoding" value="UTF-8" /> <package name="json" extends="json-default"> <action name="previewImage" class="com.action.ImageAction" method="previewImage"> <!-- 动态设置Action的属性值,预览时图片放在temp文件夹中 --> <param name="savePath">/temp</param> <result type="json"> <param name="contentType">text/html</param> </result> </action> <action name="uploadImage" class="com.action.ImageAction" method="uploadImage"> <!-- 动态设置Action的属性值,上传时图片放在user文件夹中 --> <param name="savePath">/user</param> <result type="json"> <param name="contentType">text/html</param> </result> </action> </package> </struts>
action 的文件 代码
package com.action; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.CropImageFilter; import java.awt.image.FilteredImageSource; import java.awt.image.ImageFilter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.HashMap; import java.util.Map; import java.util.Random; import javax.imageio.ImageIO; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.util.MyJsonUtil; public class ImageAction extends ActionSupport { // 封装上传或预览文件头像图片域的属性 private File image; // 封装上上传或预览文件头像图片类型的属性 private String imageContentType; // 封装上传或预览文件头像图片名的属性 private String imageFileName; // 直接在struts.xml文件中配置的属性 private String savePath; // 记录要截取的图片的起始位置 以及 宽度和高度 private Integer x1; private Integer x2; private Integer y1; private Integer y2; private Integer width; private Integer height; //返回相关操作的结果 private String result; public String getResult() { return result; } public void setResult(String result) { this.result = result; } // 返回上传文件的保存位置 public String getSavePath() { System.out.println("getSavePath() 方法被调用----->"); System.out.println("savepath=" + ServletActionContext.getRequest().getRealPath(savePath)); return ServletActionContext.getRequest().getRealPath(savePath); } public void setSavePath(String savePath) { System.out.println("setSavePath() 方法被调用----->"); this.savePath = savePath; } /** * 图片预览========》》实现说明:将客户端的图片暂时保存在服务器端,将图片以流的方式输出存放 * * @return */ public String previewImage1() throws Exception { System.out.println(" previewImage()方法被调用----->"); // 输出文件流 FileOutputStream fos = new FileOutputStream(getSavePath() + "\\" + "user.jpg"); // 输入文件流 FileInputStream fis = new FileInputStream(getImage()); //接下来是将 指定图片 输出到 指定文件夹中 byte[] buffer = new byte[1024]; int len = 0; while ((len = fis.read(buffer)) > 0) { fos.write(buffer, 0, len); } fos.flush(); fos.close(); Map<String, String> map = new HashMap<String, String>(); map.put("message", "previewImageSuccess"); Random r = new Random(); int id = r.nextInt(); //这里一定要注意,因为在服务器上的图片是按照http协议来访问的,而http是以/分隔的,所以不能是\\,而应该是/ String imagePath = "temp" + "/" + "user.jpg" + "?id=" + id; map.put("imagePath", imagePath); result = MyJsonUtil.map2json(map); System.out.println(result); //这里的返回类型设置是重点。否则会报错,必须设置成text/html;如果设置成application/json IE下会有问题,chrome没问题的。 ServletActionContext.getResponse().setContentType("text/html;charset=utf-8"); ServletActionContext.getResponse().setCharacterEncoding("utf-8"); ServletActionContext.getResponse().getWriter().write(result); //一定要再加\"\"符号,不然会报错!! //记住:write出去的也是一个json字符串,所以最好不要自己去拼 //因为你不知道一些特殊符号在json具体是怎么表示的,比如\ ServletActionContext.getResponse().getWriter().flush(); ServletActionContext.getResponse().getWriter().close(); return SUCCESS; } /** * 图片预览并将图片放大或缩小到指定大小========》》实现说明:将客户端的图片暂时保存在服务器端,然后修改图片大小,将图片 * 变成统一的大小,然后输出存放 * @return */ public String previewImage() throws Exception { System.out.println(" previewImage()方法被调用----->"); // 输出文件流 FileOutputStream fos = new FileOutputStream(getSavePath() + "\\" + "user.jpg"); // 输入文件流 FileInputStream fis = new FileInputStream(getImage()); //修改上传图片的大小==》》将图片修改成180*180 规格大小的图片 BufferedImage src = ImageIO.read(getImage()); // 读入文件 Image image = src.getScaledInstance(180, 180, Image.SCALE_DEFAULT); BufferedImage tag = new BufferedImage(180, 180, BufferedImage.TYPE_INT_RGB); Graphics g = tag.getGraphics(); g.drawImage(image, 0, 0, null); // 绘制缩小后的图 g.dispose(); ImageIO.write(tag, "jpg", fos); // 输出到文件流 Map<String, String> map = new HashMap<String, String>(); map.put("message", "previewImageSuccess"); Random r = new Random(); int id = r.nextInt(); //这里一定要注意,因为在服务器上的图片是按照http协议来访问的,而http是以/分隔的,所以不能是\\,而应该是/ String imagePath = "temp" + "/" + "user.jpg" + "?id=" + id; map.put("imagePath", imagePath); result = MyJsonUtil.map2json(map); System.out.println(result); //这里的返回类型设置是重点。否则会报错,必须设置成text/html;如果设置成application/json IE下会有问题,chrome没问题的。 ServletActionContext.getResponse().setContentType("text/html;charset=utf-8"); ServletActionContext.getResponse().setCharacterEncoding("utf-8"); ServletActionContext.getResponse().getWriter().write(result); //一定要再加\"\"符号,不然会报错!! //记住:write出去的也是一个json字符串,所以最好不要自己去拼 //因为你不知道一些特殊符号在json具体是怎么表示的,比如\ ServletActionContext.getResponse().getWriter().flush(); ServletActionContext.getResponse().getWriter().close(); return SUCCESS; } /** * 图片上传 * * @return */ public String uploadImage() throws Exception { System.out.println(" uploadImage()方法被调用----->"); System.out.println("将截取图片的参数:x1=" + x1 + ",y1=" + y1 + ",x2=" + x2 + ",y2=" + y2 + ",width=" + width + ",height=" + height); // 输出文件流 FileOutputStream fos = new FileOutputStream(getSavePath() + "/user.jpg"); // 输入文件流 FileInputStream fis = new FileInputStream(getImage()); //图片缓存区 BufferedImage bufferedImage = ImageIO.read(fis); //获取原图的大小 int srcWidth = bufferedImage.getWidth(); // 源图宽度 int srcHeight = bufferedImage.getHeight(); // 源图高度 System.out.println("原图的大小:srcWidth=" + srcWidth + ",srcHeight=" + srcHeight); if (srcWidth >= width && srcHeight >= height) { //获得该图片 Image image = bufferedImage.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT); //截取过滤器 ImageFilter cropFilter = new CropImageFilter(x1, y1, width, height); //获得截取后的图片 Image cropImage = Toolkit.getDefaultToolkit().createImage( new FilteredImageSource(image.getSource(), cropFilter)); // 这个会使得图片的背景灰度不同 int type = BufferedImage.TYPE_INT_RGB; //接下来是将图片 写入到 图片缓冲区中 BufferedImage tag = new BufferedImage(width, height, type); Graphics2D g = (Graphics2D) tag.getGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(cropImage, 0, 0, null); // 绘制剪切后的图 g.dispose(); //将缓冲区的图片 输出到 一个输出流 或 一个文件中 //方式1: ImageIO.write(tag, "jpg", fos); /*//方式2: ImageIO.write(tag,"jpg", new File(getSavePath() + "\\" + "user.jpg"));*/ Map<String, String> map = new HashMap<String, String>(); map.put("message", "uploadImageSuccess"); Random r = new Random(); int id = r.nextInt(); String imagePath = "user" + "/" + "user.jpg" + "?id=" + id; map.put("imagePath", imagePath); result = MyJsonUtil.map2json(map); System.out.println(result); //这里的返回类型设置是重点。否则会报错,必须设置成text/html;如果设置成application/json IE下会有问题,chrome没问题的。 ServletActionContext.getResponse().setContentType("text/html;charset=utf-8"); ServletActionContext.getResponse().setCharacterEncoding("utf-8"); ServletActionContext.getResponse().getWriter().write(result); //一定要再加\"\"符号,不然会报错!! //记住:write出去的也是一个json字符串,所以最好不要自己去拼 //因为你不知道一些特殊符号在json具体是怎么表示的,比如\ ServletActionContext.getResponse().getWriter().flush(); ServletActionContext.getResponse().getWriter().close(); return SUCCESS; } result = getJsonString("uploadImageError"); return ERROR; } private String getJsonString(String s){ Map<String, String> map = new HashMap<String, String>(); map.put("message", s); String json = MyJsonUtil.map2json(map); return json; } public File getImage() { return image; } public void setImage(File image) { this.image = image; } public String getImageContentType() { return imageContentType; } public void setImageContentType(String imageContentType) { this.imageContentType = imageContentType; } public String getImageFileName() { return imageFileName; } public void setImageFileName(String imageFileName) { this.imageFileName = imageFileName; } public Integer getX1() { return x1; } public void setX1(Integer x1) { this.x1 = x1; } public Integer getX2() { return x2; } public void setX2(Integer x2) { this.x2 = x2; } public Integer getY1() { return y1; } public void setY1(Integer y1) { this.y1 = y1; } public Integer getY2() { return y2; } public void setY2(Integer y2) { this.y2 = y2; } public Integer getWidth() { return width; } public void setWidth(Integer width) { this.width = width; } public Integer getHeight() { return height; } public void setHeight(Integer height) { this.height = height; } }
还要有就是要有工具类的代码 处理图片的截取文件 的
package com.util; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class ImageUtil { /** * 对图片进行放大 * * @param originalImage * 原始图片 * @param times * 放大倍数 * @return */ public static BufferedImage zoomInImage(BufferedImage originalImage, Integer times) { int width = originalImage.getWidth() * times; int height = originalImage.getHeight() * times; BufferedImage newImage = new BufferedImage(width, height, originalImage.getType()); Graphics g = newImage.getGraphics(); g.drawImage(originalImage, 0, 0, width, height, null); g.dispose(); return newImage; } /** * 对图片进行放大 * * @param srcPath * 原始图片路径(绝对路径) * @param newPath * 放大后图片路径(绝对路径) * @param times * 放大倍数 * @return 是否放大成功 */ public static boolean zoomInImage(String srcPath, String newPath, Integer times) { BufferedImage bufferedImage = null; try { File of = new File(srcPath); if (of.canRead()) { bufferedImage = ImageIO.read(of); } } catch (IOException e) { // TODO: 打印日志 return false; } if (bufferedImage != null) { bufferedImage = zoomInImage(bufferedImage, times); try { // TODO: 这个保存路径需要配置下子好一点 ImageIO.write(bufferedImage, "JPG", new File(newPath)); // 保存修改后的图像,全部保存为JPG格式 } catch (IOException e) { // TODO 打印错误信息 return false; } } return true; } /** * 对图片进行缩小 * * @param originalImage * 原始图片 * @param times * 缩小倍数 * @return 缩小后的Image */ public static BufferedImage zoomOutImage(BufferedImage originalImage, Integer times) { int width = originalImage.getWidth() / times; int height = originalImage.getHeight() / times; BufferedImage newImage = new BufferedImage(width, height, originalImage.getType()); Graphics g = newImage.getGraphics(); g.drawImage(originalImage, 0, 0, width, height, null); g.dispose(); return newImage; } /** * 对图片进行缩小 * * @param srcPath * 源图片路径(绝对路径) * @param newPath * 新图片路径(绝对路径) * @param times * 缩小倍数 * @return 保存是否成功 */ public static boolean zoomOutImage(String srcPath, String newPath, Integer times) { BufferedImage bufferedImage = null; try { File of = new File(srcPath); if (of.canRead()) { bufferedImage = ImageIO.read(of); } } catch (IOException e) { // TODO: 打印日志 return false; } if (bufferedImage != null) { bufferedImage = zoomOutImage(bufferedImage, times); try { // TODO: 这个保存路径需要配置下子好一点 ImageIO.write(bufferedImage, "JPG", new File(newPath)); // 保存修改后的图像,全部保存为JPG格式 } catch (IOException e) { // TODO 打印错误信息 return false; } } return true; } public static void main(String[] args) { boolean testIn = zoomInImage("E:/images/1.jpg", "E:\\images\\in.jpg", 4); if (testIn) { System.out.println("in ok"); } boolean testOut = zoomOutImage("E:/images/1.jpg", "E:\\images\\out.jpg", 4); if (testOut) { System.out.println("out ok"); } } }
要记住文件的 转换 json 工具类
package com.util; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sf.json.JsonConfig; import net.sf.json.processors.JsonValueProcessor; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; /** * json格式字符串辅助类 * @author chenyouhuang * */ public class MyJsonUtil { //第一部分:java2json /** * String类型转换成json格式字符串 * @param json * @return */ public static String string2json(String json){ JSONObject jsonObject = JSONObject.fromObject(json); return jsonObject.toString(); } /** * 数组转换成json格式字符串 * @param s * @return */ public static String array2json(String[] s){ JSONArray jsonArray = JSONArray.fromObject(s); return jsonArray.toString(); } /** * List集合转换成json格式字符串 * @param list * @return */ public static String list2json(List list){ JSONArray jsonArray = JSONArray.fromObject(list); return jsonArray.toString(); } /** * Map集合转换成json格式字符串 * @param map * @return */ public static String map2json(Map map){ JSONObject jsonObject = JSONObject.fromObject(map); return jsonObject.toString(); } /** * object对象转换成json格式字符串 * @param object * @return */ public static String bean2json(Object object){ JSONObject jsonObject = JSONObject.fromObject(object); return jsonObject.toString(); } /** * object对象转换成json格式字符串,并将object对象中date类型的属性按规定的输出方式格式化到json字符串中 * @param object * @param datePattern * 输出的json字符串中日期的格式 * @return */ public static String bean2jsonAndDateFormate(Object object,String datePattern){ JsonConfig jsonConfig = new JsonConfig(); JsonValueProcessor jsonValueProcessor = new JsonDateValueProcessor(datePattern); jsonConfig.registerJsonValueProcessor(Date.class, jsonValueProcessor); JSONObject jsonObject = JSONObject.fromObject(object, jsonConfig); return jsonObject.toString(); } //第二部分:json2java /** * json格式字符串转换成object对象 * @param json * 传入的json字符串 * @param objectClass * 要转换成的object的类型 * @param classMap * 该object类型的属性分别对应的类型的map * @return */ public static Object json2bean(String json,Class objectClass,Map<String,Class<?>> classMap){ Object object = JSONObject.toBean(JSONObject.fromObject(json), objectClass, classMap); return object; } /** * json格式字符串转换成List集合 * @param json * 传入的json字符串 * @return */ public static List json2list(String json){ List<String> list = (List<String>)JSONArray.toCollection(JSONArray.fromObject(json)); return list; } /** * json格式字符串转换成Map集合 * @param json * 传入的json字符串 * @return */ public static Map json2map(String json){ Map<String, Object> map = (Map<String, Object>) JSONObject.toBean(JSONObject.fromObject(json), Map.class); return map; } //第三部分:json常用对象的操作 /** * JSONObject的相关操作示例 */ public static void jsonObjectOperation(JSONObject jsonObject){ String x = jsonObject.getString("x"); jsonObject.put("key", "value"); } /** * JSONArray的相关操作示例 */ public static void jsonArrayOperation(JSONArray jsonArray){ for (int i = 0; i < jsonArray.size(); i++) { System.out.println(jsonArray.get(i)); } } //第四部分,使用gson解析json,而不是用json自己解析json /** * 使用gson将object对象列表转换成json字符串 * @param objectList * @return */ public static String gson_beans2jsonAndDateFormat(List objectList){ //google的Gson类在使用解析Date时自己制定Date的format: Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create(); String json = gson.toJson(objectList); return json; } /** * 使用gson将json字符串转换成object对象列表 * @param json * @return */ public static List gson_json2beans(String json){ Gson gson = new Gson(); List list = gson.fromJson(json, new TypeToken<List>(){}.getType()); return list; } } //processor 处理器 /** * JSON日期格式处理(java转化为JSON) */ class JsonDateValueProcessor implements JsonValueProcessor { /** * datePattern */ private String datePattern = "yyyy-MM-dd"; /** * 无参 和 有参 构造方法 */ public JsonDateValueProcessor() { super(); } public JsonDateValueProcessor(String datePattern) { super(); this.datePattern = datePattern; } /** * 自定义的process方法 */ private Object process(Object value) { try { if(value instanceof Date){ SimpleDateFormat sdf = new SimpleDateFormat(datePattern, Locale.UK); return sdf.format((Date)value); } return value == null ? "" : value.toString(); } catch (Exception e) { return ""; } } public Object processArrayValue(Object value, JsonConfig jsonConfig) { return process(value); } public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) { return process(value); } /** * get 和 set方法 * @return */ public String getDatePattern() { return datePattern; } public void setDatePattern(String datePattern) { this.datePattern = datePattern; } }
我把代码上传到云盘 可以下载 http://pan.baidu.com/s/1mgHhTiS