欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java webApp异步上传图片实现代码

程序员文章站 2024-03-12 15:20:08
如何实现java webapp异步上传图片,先了解以下几个问题: 1.图片上传; 2.图片上传预览; 3.上传图片更改地址异步添加到数据库; 主要内容 本示...

如何实现java webapp异步上传图片,先了解以下几个问题:

1.图片上传;
2.图片上传预览;
3.上传图片更改地址异步添加到数据库;

主要内容
本示例主要采用纯html前端和javascript代码作工具,查询有关demo其实现图片上传的代码范例如下:
(1)点击上传图片的div代码:

<div id="div1" class="photo"> 
 <input type="file" id="choose" accept="image/*" multiple >
 <a id="upload">上传图片</a> 
 <a class="myinputimg" onclick="selectphoto();">从图库中选择</a>
 <a class="myinputimg" id="back">取消</a>
</div>

(2)javascript代码

<script type="text/javascript">
 //获取上传图片的input表单元素
 var filechooser = document.getelementbyid("choose");
 //创建用于压缩图片的canvas
 var canvas = document.createelement("canvas");
 //获取canvas的视觉属性
 var ctx = canvas.getcontext('2d');
 //瓦片canva
 var tcanvas = document.createelement("canvas");
 var tctx = tcanvas.getcontext("2d");
 //画布的大小
 var maxsize = 100 * 1024;
 //上传图片点击事件
 $("#upload").on("click", function() {
  filechooser.click();
  })
  .on("touchstart", function() {
  //添加元素属性
  $(this).addclass("touch");
  })
  .on("touchend", function() {
  //移除元素属性
  $(this).removeclass("touch");
  });
 //元素改变 
 filechooser.onchange = function() {
 //如果选择为空,返回操作
 if (!this.files.length) return;
 //创建上传图片的数组
 var files = array.prototype.slice.call(this.files);
 //选择为数量大于1张时,反回操作,这里根据需求设定;pc端测试一次可以上传若干张图片,移动端选择一张,页面只能预览一张。由于是移动端,所以作此判断。
 if (files.length >1) {
  alert("一次只能上传1张图片");
  return;
 }
 //遍历上传图片的文件数组,可不用遍历,直接取即可。
 files.foreach(function(file, i) {
 //判断图片格式
  if (!/\/(?:jpeg|png|gif)/i.test(file.type)) return;
  var reader = new filereader();
  var li = document.createelement("li");
//   获取图片大小
  var size = file.size / 1024 > 1024 ? (~~(10 * file.size / 1024 / 1024)) / 10 + "mb" : ~~(file.size / 1024) + "kb";
  //图片预览
  li.innerhtml = '<div class="progress"><span></span></div><div class="size">' + size + '</div>';
  //追加图片预览代码;
  $(".img-list").append($(li));
  reader.onload = function() {
  var result = this.result;
  var img = new image();
  img.src = result;
  //图片显示
  $(li).css("background-image", "url(" + result + ")");
  //如果图片大小小于100kb,则直接上传
  if (result.length <= maxsize) {
   img = null;
   upload(result, file.type, $(li));
   return;
  }
//  图片加载完毕之后进行压缩,然后上传
  if (img.complete) {
   callback();
  } else {
   img.onload = callback;
  }
  function callback() {
   var data = compress(img);
   upload(data, file.type, $(li));
   img = null;
  }
  };
  reader.readasdataurl(file);
 });
 };
 //以下是图片压缩相关;
 //使用canvas对大图片进行压缩
 function compress(img) {
 var initsize = img.src.length;
 var width = img.width;
 var height = img.height;
 //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
 var ratio;
 if ((ratio = width * height / 4000000) > 1) {
  ratio = math.sqrt(ratio);
  width /= ratio;
  height /= ratio;
 } else {
  ratio = 1;
 }
 canvas.width = width;
 canvas.height = height;
 //铺底色
 ctx.fillstyle = "#fff";
 ctx.fillrect(0, 0, canvas.width, canvas.height);
 //如果图片像素大于100万则使用瓦片绘制
 var count;
 if ((count = width * height / 1000000) > 1) {
  count = ~~(math.sqrt(count) + 1); //计算要分成多少块瓦片
 // 计算每块瓦片的宽和高
  var nw = ~~(width / count);
  var nh = ~~(height / count);
  tcanvas.width = nw;
  tcanvas.height = nh;
  for (var i = 0; i < count; i++) {
  for (var j = 0; j < count; j++) {
   tctx.drawimage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
   ctx.drawimage(tcanvas, i * nw, j * nh, nw, nh);
  }
  }
 } else {
  ctx.drawimage(img, 0, 0, width, height);
 }
 //进行最小压缩
 var ndata = canvas.todataurl('image/jpeg', 0.1);
 console.log('压缩前:' + initsize);
 console.log('压缩后:' + ndata.length);
 console.log('压缩率:' + ~~(100 * (initsize - ndata.length) / initsize) + "%");
 tcanvas.width = tcanvas.height = canvas.width = canvas.height = 0;
 return ndata;
 }
 //图片上传,将base64的图片转成二进制对象,塞进formdata上传
 function upload(basestr, type, $li) {
 var text = window.atob(basestr.split(",")[1]);
 var buffer = new uint8array(text.length);
 var pecent = 0, loop = null;
 for (var i = 0; i < text.length; i++) {
  buffer[i] = text.charcodeat(i);
 }
 var blob = getblob([buffer], type);
 var xhr = new xmlhttprequest();
 var formdata = getformdata();
 formdata.append('upload', blob);
 //异步请求kindeditor插件的上传图片jsp页面
 xhr.open('post', '<%=request.getcontextpath()%>/kindeditor/jsp/upload_json.jsp');
 xhr.onreadystatechange = function() {
  if (xhr.readystate == 4 && xhr.status == 200) { 
  //返回服务器端的图片地址 
  var face_img=xhr.responsetext;
  var id=$("#arid").text();
  //异步像数据库中添加图片
  $.ajax({
   type:"post",
   //异步请求struts的action类将图片地址插入数据库
   url:"add_article_faceurl.action",
   datatype:"json",
   data:"faceurl="+face_img+"&id="+id,
   async:true,
   success: function(msg){ 
   //取添加数据库中的图片相关的id值,存入页面隐藏区域
    $("#arid").text(msg);
   },
   error: function(a){}
  });   
  }
 };
 //模拟上传进度显示
 //数据发送进度,前50%展示该进度
 xhr.upload.addeventlistener('progress', function(e) {
  if (loop) return;
  pecent = ~~(100 * e.loaded / e.total) / 2;
  $li.find(".progress span").css('width', pecent + "%");
  if (pecent == 50) {
  mockprogress();
  }
 }, false);
 //数据后50%用模拟进度
 function mockprogress() {
  if (loop) return;
  loop = setinterval(function() {
  pecent++;
  $li.find(".progress span").css('width', pecent + "%");
  if (pecent == 99) {
   clearinterval(loop);
  }
  }, 100);
 }
 xhr.send(formdata);
 }
 /**
 * 获取blob对象的兼容性写法
 * @param buffer
 * @param format
 * @returns {*}
 */
 function getblob(buffer, format) {
 try {
  return new blob(buffer, {type: format});
 } catch (e) {
  var bb = new (window.blobbuilder || window.webkitblobbuilder || window.msblobbuilder);
  buffer.foreach(function(buf) {
  bb.append(buf);
  });
  return bb.getblob(format);
 }
 }
 /**
 * 获取formdata
 */
 function getformdata() {
 var isneedshim = ~navigator.useragent.indexof('android')
  && ~navigator.vendor.indexof('google')
  && !~navigator.useragent.indexof('chrome')
  && navigator.useragent.match(/applewebkit\/(\d+)/).pop() <= 534;
 return isneedshim ? new formdatashim() : new formdata();
 }
 /**
 * formdata 补丁, 给不支持formdata上传blob的android机打补丁
 * @constructor
 */
 function formdatashim() {
 console.warn('using formdata shim');
 var o = this,
  parts = [],
  boundary = array(21).join('-') + (+new date() * (1e16 * math.random())).tostring(36),
  oldsend = xmlhttprequest.prototype.send;
 this.append = function(name, value, filename) {
  parts.push('--' + boundary + '\r\ncontent-disposition: form-data; name="' + name + '"');
  if (value instanceof blob) {
  parts.push('; filename="' + (filename || 'blob') + '"\r\ncontent-type: ' + value.type + '\r\n\r\n');
  parts.push(value);
  }
  else {
  parts.push('\r\n\r\n' + value);
  }
  parts.push('\r\n');
 };
 // override xhr send()
 xmlhttprequest.prototype.send = function(val) {
  var fr,
   data,
   oxhr = this;
  if (val === o) {
  // append the final boundary string
  parts.push('--' + boundary + '--\r\n');
  // create the blob
  data = getblob(parts);
  // set up and read the blob into an array to be sent
  fr = new filereader();
  fr.onload = function() {
   oldsend.call(oxhr, fr.result);
  };
  fr.onerror = function(err) {
   throw err;
  };
  fr.readasarraybuffer(data);
  // set the multipart content type and boudary
  this.setrequestheader('content-type', 'multipart/form-data; boundary=' + boundary);
  xmlhttprequest.prototype.send = oldsend;
  }
  else {
  oldsend.call(this, val);
  }
 };
 }
</script>

(3)kindeditor插件的上传图片jsp页面相关代码.

<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%>
<%@ page import="java.util.*,java.io.*" %>
<%@ page import="java.text.simpledateformat" %>
<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="org.apache.commons.fileupload.disk.*" %>
<%@ page import="org.apache.commons.fileupload.servlet.*" %>
<%@ page
 import="org.apache.struts2.dispatcher.multipart.multipartrequestwrapper"%>
<%@ page import="org.json.simple.*" %>
<%

/**
 * kindeditor jsp
 * 
 * 本jsp程序是演示程序,建议不要直接在实际项目中使用。
 * 如果您确定直接使用本程序,使用之前请仔细确认相关安全设置。
 * 
 */

//文件保存目录路径
string savepath = pagecontext.getservletcontext().getrealpath("/") + "attached/";
//string savepath = "http:\\\\192.168.1.226:8080\\qslnbase\\uploadfile/";
//string savepath = "d:/www/qslnadp/adp/webroot/kindeditor/attached/";
//文件保存目录url
string saveurl = request.getcontextpath() + "/attached/";
//定义允许上传的文件扩展名
hashmap<string, string> extmap = new hashmap<string, string>();
extmap.put("image", "gif,jpg,jpeg,png,bmp,blob");
extmap.put("flash", "swf,flv");
extmap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb");
extmap.put("file", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2");

//最大文件大小
long maxsize = 1000000;

response.setcontenttype("text/html; charset=utf-8");

if(!servletfileupload.ismultipartcontent(request)){
 out.println(geterror("请选择文件。"));
 return;
}
//检查目录
file uploaddir = new file(savepath);
if(!uploaddir.isdirectory()){
 out.println(geterror("上传目录不存在。"));
 return;
}
//检查目录写权限
if(!uploaddir.canwrite()){
 out.println(geterror("上传目录没有写权限。"));
 return;
}

string dirname = request.getparameter("dir");
if (dirname == null) {
 dirname = "image";
}
if(!extmap.containskey(dirname)){
 out.println(geterror("目录名不正确。"));
 return;
}
//创建文件夹
savepath += dirname + "/";
saveurl += dirname + "/";
file savedirfile = new file(savepath);
if (!savedirfile.exists()) {
 savedirfile.mkdirs();
}
simpledateformat sdf = new simpledateformat("yyyymmdd");
string ymd = sdf.format(new date());
savepath += ymd + "/";
saveurl += ymd + "/";
file dirfile = new file(savepath);
if (!dirfile.exists()) {
 dirfile.mkdirs();
}
//struts2 请求 包装过滤器
multipartrequestwrapper wrapper = (multipartrequestwrapper) request;

//获得上传 的文件名
string filename1 = wrapper.getfilenames("upload")[0];

//获得文件过滤器
file file = wrapper.getfiles("upload")[0];

//检查文件大小
if(file.length() > maxsize){
 out.println(geterror("上传文件大小超过限制。"));
 return;
}

//检查扩展名
string fileext1 = filename1.substring(filename1.lastindexof(".") + 1).tolowercase();
//重构上传文件名
simpledateformat df1 = new simpledateformat("yyyymmddhhmmss");
string newfilename1 = df1.format(new date()) + "_" + new random().nextint(1000) + "." + fileext1;

byte[] buffer = new byte[1024];
//获取文件输出流
fileoutputstream fos = new fileoutputstream(savepath + newfilename1);
string url=savepath + newfilename1;
out.println(url);
//获取内存中当前文件输入流
inputstream in = new fileinputstream(file);

try {
 int num = 0;
 while ((num = in.read(buffer)) > 0) {
  fos.write(buffer, 0, num);
 }
} catch (exception e) {
 e.printstacktrace(system.err);
} finally {
 in.close();
 fos.close();
}
%>
<%!
private string geterror(string message) {
 jsonobject obj = new jsonobject();
 obj.put("error", 1);
 obj.put("message", message);
 return obj.tojsonstring();
}
%>

4)有关kindeditor上传图片的jar包有如下所示
a.commons-fileupload-1.2.1.jar
b.commons-io-1.4.jar
c.json_simple-1.1.jar

这里没有用到有关于kindeditor的js代码,具体可参考:kindeditor实现图片自动上传功能

(5)有关kindeditor上传图片预览的div如下

<div id="div2">
 <ul class="img-list">
  <li id="wy">
   <img style="height:100%;width:100%;position:absolute;top:0px;" src="<%=request.getcontextpath()%>/shequ/images/index.png;" >
  </li>
 </ul> 
</div>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。