最近开发的项目中,有需要对上传的图片进行二次截图,然后再上传的功能,本人使用的是jquery的imgareaselect插件进行的截图。
在详细介绍如何使用之前,先讲一下进行截图的思路:先将本地的图片上传至资源服务器,然后将资源服务器上的图片下载至项目中,对下载的图片进行切割,将切割好的图片上传至资源服务器并删除下载到项目中的原图。其实可以直接将本地的图片下载到项目中,但是本地图片的地址不太好拿,上传到资源服务器以后地址就好拿了,至于为什么不直接切割远程的图片,直接从远程切割图片切割不了,只能下载到本地项目了。
还有一点需要注意:从资源服务器下载到项目中的图片,在页面展示的时候可能由于整体样式问题,会在页面被压缩,你在该页面上截图以后,会在后进行同比例的计算。例如一个图片是700*500的,但是由于页面样式问题,展示是图片最大350*350,由于这里高是700,宽是500,被压缩以后展示的图片就是高350,宽进行等比压缩就是250,变成350*250的图,然后在该图上进行截图,我们在后台原图(700*500的图)上会进行等比计算,计算出在原图上应该是什么位置,多宽多高。
下面就是代码展示了:
首先是相关插件的导入了(插件我上传到我csdn资源上了,有需要的可以下载):
https://download.csdn.net/download/xiaoye319/10926138
接着就是在页面上的具体代码(我这个是jsp页面):有一块内容展示的是
从本地上传图片的按钮,然后还有隐藏一块内容,用来展示从上传到资源服务器的原图,就是在这块内容上进行截图。
<%--上传店内图片--%>
添加图片建议上传不少于3张,最多可传9张图片格式为jpg,png,每张大小不超过1M,数量3的倍数为最佳
裁剪照片
接下来就是js部分了,上传本地图片到资源服务器上,返回url到截图展示区域展示,然后截图到后台:
//添加图片
function addUpGoodImg() {
$('.upGoodImg').click()
}
// 上传店内图片
function upGoodImg (elem) {
var formData = new FormData(),
file = elem[0],
fileSize = file.files[0].size;
if ( Math.round(fileSize/1024)/1000 > 1 ) {
$.JsDialog.Alert("提示", '图标过大上传会失败!');
return
}
formData.append('file', file.files[0]);
$.ajax({
type: 'post',
url: newUploadURL,
contentType: false, //这个一定要写
processData: false, //这个也一定要写,不然会报错
data:formData,
dataType:'json', //返回类型,有json,text,HTML。这里并没有jsonp格式,所以别妄想能用jsonp做跨域了。
beforeSend: function () {
$('.page-loading').show()
}, success:function(data){
$("#x1,#y1,#width,#height").val("");
$("#cutphoto").attr("src",data.file_url);
$("#add-rorder-cover").addClass('show');
cutImg("1:1");
$('.page-loading').hide()
}, error: function(XMLHttpRequest, textStatus, errorThrown, data){
$.JsDialog.Alert('上传失败,请稍后重试.')
}
})
}
// 截取照片方法
function cutImg(s){
$('#cutphoto').imgAreaSelect({
aspectRatio: s,
onSelectEnd: function (img, selection) {
$('input[name="x1"]').val(selection.x1);
$('input[name="y1"]').val(selection.y1);
$('input[name="width"]').val(selection.width);
$('input[name="height"]').val(selection.height);
}
});
}
// 确定截取照片
function cutPhoto(){
if($("#x1").val().length > 0 && $("#y1").val().length > 0 && $("#width").val().length > 0 && $("#height").val().length > 0){
$(".loading").show();
$.ajax({
type : "POST",
url : "${ctx}/sys/office/ajaxCutImg",
data:{'path':$("#cutphoto").attr("src"),'x':$("#x1").val(),'y':$("#y1").val(),'width':$("#width").val(),'height':$("#height").val()},
dataType: 'text',
success: function(str) {
$(".loading").hide();//隐藏展示层
closeCutPhoto();
var data = $.parseJSON(str);
console.log(data)
if(data.status == 200){
$("#goodsDetailsImages").before().append(''
+''
+'');
$("#uploadLists").hide();
$('.upGoodImg').val('')
}else{
top.layer.alert('截图出现异常!', {icon: 0});
}
},
error:function(data){
top.layer.alert('截图出现异常!', {icon: 0});
}
});
}else{
top.layer.alert('未截取图片!请重新截取!', {icon: 0});
}
}
// 关闭截图弹出框
function closeCutPhoto(){
$('#cutphoto').imgAreaSelect({
remove:true
});
$("#add-rorder-cover").removeClass('show');
}
其中cutImg()方法是设置截图的比例,设置为1:1或者1:2等,若不传入参数,则代表自由截取;cutPhoto()方法是在页面选取好想要截取的图片以后请求后台在原图上进行计算,成功以后上传到资源服务器,然后返回截取后的图片在资源服务器上的地址。
下面是后台计算方法:
/**
* 截图
* @param path
* @param x
* @param y
* @param width
* @param height
* @param request
* @return
*/
@ResponseBody
@SuppressWarnings("null")
@RequestMapping(value = "ajaxCutImg")
public String ajaxCutImg(String path,int x,int y,int width,int height,HttpServletRequest request){
JSONObject josn = new JSONObject();
JSONObject josnIO = new JSONObject();
try {
// 下载照片到本地
josnIO = convertIO(path,request,logger);
if("200".equals(josnIO.get("status"))){
// 截图保存到本地
String string = cutImg(josnIO.get("msg").toString(), x, y, width, height,request,logger);
if("true".equals(string)){
// 上传本地照片到服务器
josn = postImg(josnIO.get("msg").toString(),request,logger);
}else{
josn.put("status", "-1");
josn.put("msg","截图出现异常,请联系管理员");
}
}else{
josn.put("status", "-1");
josn.put("msg","截图出现异常,请联系管理员");
}
} catch (Exception e) {
BugLogUtils.saveBugLog(request, "截图出现异常", e);
logger.error("截图错误信息:"+e.getMessage());
josn.put("status", "-1");
josn.put("msg","截图出现异常,请联系管理员");
return josn.toString();
}
boolean success = (new File(josnIO.get("msg").toString())).delete();
if (success) {
System.out.println("删除本地照片成功: " + josnIO.get("msg").toString());
} else {
System.out.println("删除本地照片失败: " + josnIO.get("msg").toString());
}
System.out.println(josn.get("msg"));
return josn.toString();
}
// 下载图片到本地
public JSONObject convertIO(String path,HttpServletRequest request,org.slf4j.Logger logger){
// 返回结果集
JSONObject josn = new JSONObject();
try {
//new一个URL对象
URL url = new URL(path);
//打开链接
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//设置请求方式为"GET"
conn.setRequestMethod("GET");
//超时响应时间为5秒
conn.setConnectTimeout(5 * 1000);
//通过输入流获取图片数据
InputStream inStream = conn.getInputStream();
//得到图片的二进制数据,以二进制封装得到数据,具有通用性
byte[] data = readInputStream(inStream);
// 截取原照片后缀
String string = path.substring(path.lastIndexOf(".") + 1);
TrainRuleParam trainRuleParam =new TrainRuleParam();
trainRuleParam.setParamKey("excel_path");
//本地项目地址:
//String newURL = "E:/XXX/src/main/webapp/static/cutImg/down_"+new java.util.Date().getTime()+"_photo."+string;
//线上项目在tomcat的地址
String newURL = ParametersFactory.getMtmyParamValues("pc_project_root_path") + "/static/cutImg/down_"+new java.util.Date().getTime()+"_photo."+string;
//new一个文件对象用来保存图片,默认保存当前工程根目录
File imageFile = new File(newURL);
//创建输出流
FileOutputStream outStream = new FileOutputStream(imageFile);
//写入数据
outStream.write(data);
//关闭输出流
outStream.close();
josn.put("status", "200");
josn.put("msg",newURL);
return josn;
} catch (Exception e) {
BugLogUtils.saveBugLog(request, "截图上传--下载图片到本地出现异常", e);
logger.error("截图上传--下载图片到本地错误信息:"+e.getMessage());
josn.put("status", "-1");
josn.put("msg","截图出现异常,请联系管理员");
return josn;
}
}
public static byte[] readInputStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//创建一个Buffer字符串
byte[] buffer = new byte[1024];
//每次读取的字符串长度,如果为-1,代表全部读取完毕
int len = 0;
//使用一个输入流从buffer里把数据读取出来
while( (len=inStream.read(buffer)) != -1 ){
//用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
outStream.write(buffer, 0, len);
}
//关闭输入流
inStream.close();
//把outStream里的数据写入内存
return outStream.toByteArray();
}
public static String cutImg(String srcImageFile, int x, int y, int destWidth, int destHeight,HttpServletRequest request,org.slf4j.Logger logger) {
try {
Image img;
ImageFilter cropFilter;
// 读取源图像
BufferedImage bi = ImageIO.read(new File(srcImageFile));
int srcWidth = bi.getWidth(); // 源图宽度
int srcHeight = bi.getHeight(); // 源图高度
logger.info("#######照片原始宽度srcWidth= " + srcWidth + "_____原始高度srcHeight= " + srcHeight);
double scale = 1;
if(srcWidth >= 350 && srcHeight >= 350){
if(srcWidth >= srcHeight){
scale = (double)srcWidth/(double)350;
}else if(srcWidth < srcHeight){
scale = (double)srcHeight/(double)350;
}else{
scale = 0;
}
}else if(srcWidth > 350 && srcHeight <= 350){
scale = (double)srcWidth/(double)350;
}else if(srcHeight > 350 && srcWidth <= 350){
scale = (double)srcHeight/(double)350;
}else{
scale = 1;
}
x = (int)(x*scale);
y = (int)(y*scale);
destWidth = (int)(destWidth*scale);
destHeight = (int)(destHeight*scale);
if (srcWidth >= destWidth && srcHeight >= destHeight) {
Image image = bi.getScaledInstance(srcWidth, srcHeight,Image.SCALE_DEFAULT);
// 改进的想法:是否可用多线程加快切割速度
// 四个参数分别为图像起点坐标和宽高
// 即: CropImageFilter(int x,int y,int width,int height)
cropFilter = new CropImageFilter(x, y, destWidth, destHeight);
img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
BufferedImage tag = new BufferedImage(destWidth, destHeight,BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(img, 0, 0, null); // 绘制缩小后的图
g.dispose();
// 截取原照片后缀
String string = srcImageFile.substring(srcImageFile.lastIndexOf(".") + 1);
// 输出为文件 覆盖原文件
ImageIO.write(tag, string, new File(srcImageFile));
return "true";
}
} catch (Exception e) {
BugLogUtils.saveBugLog(request, "截图上传--截图出现异常", e);
logger.error("截图上传--截图错误信息:"+e.getMessage());
return "false";
}
return "false";
}
// 上传本地照片到服务器
public static JSONObject postImg(String newURL,HttpServletRequest request,org.slf4j.Logger logger) {
HttpClient client = new HttpClient();
// 返回结果集
JSONObject resJson = new JSONObject();
try {
PostMethod postMethod = new PostMethod(ParametersFactory.getMtmyParamValues("uploader_url"));
// FilePart:用来上传文件的类
FilePart filePart = new FilePart("img", new File(newURL));
Part[] parts = {
filePart
};
// 对于MIME类型的请求,httpclient建议全用MulitPartRequestEntity进行包装
MultipartRequestEntity mre = new MultipartRequestEntity(parts, postMethod.getParams());
postMethod.setRequestEntity(mre);
// 执行请求,返回状态码
int status = client.executeMethod(postMethod);
if (status == HttpStatus.SC_OK) {
System.out.println("上传到服务器请求成功,返回信息:" + postMethod.getResponseBodyAsString());
resJson.put("status", "200");
resJson.put("msg",postMethod.getResponseBodyAsString());
return resJson;
} else {
System.out.println("请求上传图片,请求失败。");
resJson.put("status", "-1");
resJson.put("msg", "上传图片,请求失败。");
return resJson;
}
} catch(Exception e) {
resJson.put("status", "-1");
resJson.put("msg", "系统异常");
System.out.println("请求上传图片,请求失败。"+e.toString());
return resJson;
}
}
以上就是使用jquery的imgareaselect插件进行截图的全部过程,有问题请及时沟通