文件上传+截图+预览升级版-我们到底能走多远系列(23)
我们到底能走多远系列(23)
扯淡:新的一年开始啦,各位有志青年也该发力学习,工作,赚钱啦!
来个笑话:劫匪进某银行抢劫:钱是国家的,命是自己的!通通不许动!” 于是没有一个人动。抢劫成功。
一个新来硕士劫匪问老大:我们赶快数一下抢了多少吧。老劫匪说,你傻啊?这么多数到什么时候啊?今天晚上看新闻不就知道了吗?(各位这就是工作经验啊)
第二天劫匪们看新闻:4名劫匪,劫去某银行,1个亿...
老大开骂了:不对啊,昨天数了3边就1千万呀,马德~,这么幸苦,人家动一下嘴皮子就赚了我们9倍。再也不干抢银行了~(这就是程序员啊)
主题:
1,截图改进
年前写的,上传图片,截图:抓我 供大家参考,上次的流程是这样的,上传图片到后台,保存到文件夹,然后页面上把原尺寸的图片展现出来,进行截图,截图成功后把截图坐标尺寸返回后台,后台根据这些参数把后台的图片剪切,然后把截图的效果展现在页面。
那么这儿就有个问题啦:
就是把原图展现在页面上进行截图的时候,如果上传的图片很大,会导致页面展现很难看!
参考了博客园的头像截图,只有通过缩小原图的方式来实现,又考虑到我做的不是截什么头像这样的小图,我是要一张高分辨率的图片,如此就有了一下方案:
把原图上传后,进行等比例缩放,缩放到页面上展现框中能够展现的大小,把原图存服务器,缩放图展现在截图页面,把缩放的比例,传到页面。
然后进行截图,截图完毕后,回传坐标,在js里结合坐标和缩放比例算出实际图中截图的坐标,然后交给后台去裁剪后台的原图,这样剪切出来的图片分辨率不会失真了。
事实上,明白了整个流程,根据上次的文章,就能写出来了,所以这里就不贴很多代码了
首先截图插件使用imgAreaSelect
piso = $('#photo').imgAreaSelect({ x1: 0, y1: 0, x2: 72, y2: 128, aspectRatio: '9:16' ,onSelectEnd: preview, persistent : true, instance: true, enable:true, handles: true });
返回截图坐标的时候,用js还原成原图上的坐标:
list[0] = parseInt($("#x1").val()/sx); list[1] = parseInt($("#x2").val()/sx); list[2] = parseInt($("#y1").val()/sy); list[3] = parseInt($("#y2").val()/sy); list[4] = parseInt($("#w").val()/sx); list[5] = parseInt($("#h").val()/sy);
等比例缩放:
public static double[] saveThumbnailImage(InputStream is, String imgType, File saveFile, int width, int height,boolean equalProportion) throws IOException{ BufferedImage srcImage; if(imgType ==null || "".equals(imgType)){ imgType = "JPEG"; } srcImage=ImageIO.read(is); ImageResizeModel imageResizeModel = new ImageResizeModel(); imageResizeModel.setBuffedImage(srcImage); imageResizeModel.setSx(imageResizeModel.getSx()); imageResizeModel.setSy(imageResizeModel.getSy()); if(width>0||height>0){ ImageResizeModel imageResizeModel1 = resize(srcImage,width,height,equalProportion); imageResizeModel.setBuffedImage(imageResizeModel1.getBuffedImage()); imageResizeModel.setSx(imageResizeModel1.getSx()); imageResizeModel.setSy(imageResizeModel1.getSy()); } ImageIO.write(imageResizeModel.getBuffedImage(),imgType,saveFile); double[] ratio = new double[]{imageResizeModel.getSx(), imageResizeModel.getSy()}; return ratio; } /** * 将原图片的BufferedImage对象生成缩略图 * source:原图片的BufferedImage对象 * targetW:缩略图的宽 * targetH:缩略图的高 */ public static ImageResizeModel resize(BufferedImage source,int targetW,int targetH,boolean equalProportion){ int type=source.getType(); BufferedImage target=null; double sx=(double)targetW/source.getWidth(); double sy=(double)targetH/source.getHeight(); //这里想实现在targetW,targetH范围内实现等比例的缩放 //如果不需要等比例的缩放则下面的if else语句注释调即可 if(equalProportion){ if(sx>sy){ sx=sy; targetW=(int)(sx*source.getWidth()); }else{ sy=sx; targetH=(int)(sx*source.getHeight()); } } if(type==BufferedImage.TYPE_CUSTOM){ ColorModel cm=source.getColorModel(); WritableRaster raster=cm.createCompatibleWritableRaster(targetW,targetH); boolean alphaPremultiplied=cm.isAlphaPremultiplied(); target=new BufferedImage(cm,raster,alphaPremultiplied,null); }else{ target=new BufferedImage(targetW,targetH,type); Graphics2D g=target.createGraphics(); g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY); g.drawRenderedImage(source,AffineTransform.getScaleInstance(sx,sy)); g.dispose(); } ImageResizeModel imageResizeModel = new ImageResizeModel(); imageResizeModel.setBuffedImage(target); imageResizeModel.setSx(sx); imageResizeModel.setSy(sy); return imageResizeModel; }
ImageResizeModel :
package com.syezon.webapp.util; import java.awt.image.BufferedImage; public class ImageResizeModel { private BufferedImage buffedImage; private double sx;//x轴缩放比例 private double sy;//y轴缩放比例 public BufferedImage getBuffedImage() { return buffedImage; } public void setBuffedImage(BufferedImage buffedImage) { this.buffedImage = buffedImage; } public double getSx() { return sx; } public void setSx(double sx) { this.sx = sx; } public double getSy() { return sy; } public void setSy(double sy) { this.sy = sy; } }
看一下改进后的效果吧:
2,上传按钮改进:
页面上看到这样的框,大家是不是觉得体验不好啦?
那改成博客园这样的?刚发现的.... 说实在的,博客园的这个已经调到完美了:
事实上我们可以直接吵博客园的样式来做的现在做成这样啦:
<div class="fileWrapper" > <a class="fileButton">上传图片</a> <input name="advImage" id="advImage" class="fileInput" type="file" value="${advImage}" onchange="uploadImage()"/> </div>
懂样式的可以看看啦,
一下两个就是关键啦:
opacity: 0;
font-size:100px;
.fileInput { cursor: pointer; height: 24px; opacity: 0; position: absolute; right: 0; top: 0; font-size:100px; filter:alpha(opacity=0); width: 200px; } .fileButton { background: none repeat scroll 0 0 #fc5d73; color: #FFFFFF; cursor: pointer; display: block; float: left; font-size: 12px; height: 20px; line-height: 20px; padding: 2px 4px; text-align: center; width: 96px; } a:focus, a:active, a:hover { border: medium none; outline: medium none; } .fileWrapper { float: left; height: 24px; overflow: hidden; position: relative; width: 110px;cursor: pointer; } .fileWrapper a{color: #fff !important; text-decoration: none!important;cursor: pointer;}
效果:
3,关于window.showModalDialog 打开小页面缓存问题。
先前的代码没考虑这个问题,导致后期测试的时候才发现居然打开小页面后,下次再打开,修改的东西没有呈现....
解决方案也简单的,就是每次请求的url不一样就可以啦!
代码如下:随机数你懂的... 好像没必要 ++....先不管了...
var random = Math.round(1000); ;//每次请求的url保证不一样,决showModalDialog多次弹出时,取缓存页面问题 function show(rid) { random++; window.showModalDialog("toEditRole.html?roleId="+rid+"&random="+random,"window123","dialogHeight:510px;dialogWidth:650px;resizable:no;help:yes;status:no;scroll:auto"); }
4,取得本服务器的ip,端口
java中大家都熟悉用如下代码,在jsp中 还是在action层中取得ip地址和端口号:
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
那么在service层怎么办呢? 把request传进去不久可以啦...
是的,但是因为service层的话牵涉到业务,可能调用的方法比较多,如果每个都来个request实在是有点...
刚好用到那个dwr框架,可以直接取到request的信息:
public static String getBasePath(){ WebContext ctx = WebContextFactory.get(); HttpServletRequest request = ctx.getHttpServletRequest(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/"; return basePath; }
但是,如果是action进来的service层方法,是不能使用这个方式的哦!
抛问题啦:
你们在项目里是怎么解决这个 要取得BasePath的问题的呢? 希望得到帮助!
让我们继续前行
----------------------------------------------------------------------
努力不一定成功,但不努力肯定不会成功。
共勉。