zoukankan      html  css  js  c++  java
  • 图片上传+预览+剪切解决方案我们到底能走多远系列(20)

    我们到底能走多远系列(20)

    扯淡:12月15号预订的mx2,现在还没货,唉悲剧。本来想参加朋友婚礼前换个手机的,看来是指望不上了,朋友结婚,5星级酒店,那酒店我高中的时候每天会望望它的楼顶有没有盘旋的直升机,总算咋也能进去吃个饭喝个酒啦,咋农民也就这么点追求,哈哈。

    主题:

    图片上传,预览,剪切在很多网站上都会使用,可是到自己真正想做的时候,却遇到了各种困难很问题,总算也是完整方案出来啦。分享一下。

    表现流程如下:

    步骤1:点击浏览按钮选中图片-------1------>onchange事件把图片上传到服务器-------2----->图片路径回传

    步骤2:进入切割图片------3----->切割,取得坐标,长度--------4---->传给服务器---------->后台切割产生新图片-----5------>回传新图路径

    步骤3:页面截图预览

      步骤1:

    file标签:

    <input name="advImage" id="advImage" type="file" style="height:22px;" onchange="uploadImage()"/>

     onchange事件调用的js方法:

    ajaxFileUpload利用iframe模拟了ajax上传文件。
    url:"uploadPreviewImage.html" 就是后台地址,(本人使用的是spring mvc),
    success:function (data , status),上传成功后调用的js中,$('#photo').imgAreaSelect方法是使用了imgAreaSelect插件来初始化截图界面。
    官网地址:http://odyniec.net/projects/imgareaselect/

    关于ajaxFileUpload的api可以查看官网,开始的时候我使用的是网上随便下的一个js,发现一直调不同,最后换了官网的,才ok。
    function uploadImage(){
    // 检查图片格式
        var f=document.getElementById("advImage").value;
    
        if(!/\.(gif|jpg|jpeg|png|JPG|PNG)$/.test(f))
        {
            alert("图片类型必须是.jpeg,jpg,png中的一种")
            return false;
        }
        // 利用ajaxFileUpload js 插件上传图片
        $.ajaxFileUpload({url:"uploadPreviewImage.html",
            secureuri:false,
            fileElementId:"advImage",
            dataType:"json",
           
            success:function (data , status) {
                 //上传成功后,直接跳出截图框,使用imgAreaSelect插件
                piso = $('#photo').imgAreaSelect({ 
                      x1: 0, y1: 0, x2:480 , y2: 520 ,onSelectEnd: preview,
                resizable: false,
                instance: true,
                persistent:true
                });
                // 这个方法是现实一个div,托住截图框
                showCutImage();
                // 一些变量在页面的隐藏input的设置
                document.getElementById("photo").src = data.tempPath;
                document.getElementById("currentPath").value = data.tempPath;
                
            },
            error:function (data, status, e) {
                //alert("图片上传失败,请重新选择图片");
            }
        });
        return false;
    }
    // 截图选中后调用方法,保存好起始坐标和宽高
    function preview(img, selection)
        {
           
            $('#x1').val(selection.x1);
            $('#y1').val(selection.y1);
            $('#x2').val(selection.x2);
            $('#y2').val(selection.y2);
            $('#w').val(selection.width);
            $('#h').val(selection.height);
        }

     uploadPreviewImage方法,把文件方法零时文件夹下:

        public ModelAndView uploadPreviewImage(HttpServletRequest request, HttpServletResponse response) throws IOException{
            User user = (User)request.getSession().getAttribute("user");
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request;
            MultipartFile image = multipartRequest.getFile("advImage");
            
            response.setCharacterEncoding(BusinessConstants.ENCOD_UTF);
            response.setHeader("ContentType", "json");
            
            PrintWriter out = response.getWriter();
            
            // 组合零时图片名
            String imageName = image.getOriginalFilename();
            String file_ext = imageName.substring(imageName.lastIndexOf(BusinessConstants.DOT) + 1);
            SimpleDateFormat df = new SimpleDateFormat(BusinessConstants.DATE_FORMAT);
            String tempImageName = user.getId() +BusinessConstants.UNDERLINE + df.format(new Date()) + BusinessConstants.DOT + file_ext;        
            
            // 存放浏览图片的零时文件路径
            File file = new File(request.getSession().getServletContext().getRealPath(BusinessConstants.TEMP_PICTURE_PATH + 
                    tempImageName));
            
            byte[] advImageBytes = null;
            InputStream advImageStream = null;
            
            try {
                file.createNewFile();
                advImageStream = image.getInputStream();
                advImageBytes = FileCopyUtils.copyToByteArray(advImageStream);
                FileCopyUtils.copy(advImageBytes, file);
                advImageStream.close();
            } catch (IOException e) {
    
                e.printStackTrace();
            }
            
            String tempPath =  BusinessConstants.TEMP_RELATIVE_PICTURE_PATH + 
             tempImageName;
            
            // 传给页面相对路径
            out.print("{");  
            out.print("tempPath:'"+tempPath+"',"); 
            out.print("msg:''"); 
            out.print("}");
            out.flush();
            out.close(); 
            // ajax
            return null;
        }

     上面的uploadPreviewImage调用完成后就会把下面的div显示出来(初始隐藏):

    这就是截图界面啦!

    <div id="cutImageDiv" class="displayCutDiv" >
    <div id="cutImageShut" class="amend-close">关闭</div>
    <div style="margin: 0 auto;"><img  src="../images/test.jpg" id="photo"onclick="imgAreaSelect();"/> 
    <input id="x1" type="hidden" />
    <input id="x2" type="hidden" />
    <input id="y1" type="hidden" />
    <input id="y2" type="hidden" />
    <input id="w" type="hidden" />
    <input id="h" type="hidden" />
    
    
     </div>
     <input type="button"  id="cutImage" name="cutImage" class="btton-queren" onclick="cutImage()" style="float: right;" value="保存"/>
     </div>

      步骤2:

     我们可以看到截图完毕后点击保存,就会调用cutImage方法:

    里面我们利用dwr调用ReleaseService的cutImage方法。

    function cutImage(){
    
        var list = new Array();
        list[0] = $("#x1").val();
        list[1] = $("#x2").val();
        list[2] = $("#y1").val();
        list[3] = $("#y2").val();
        list[4] = $("#w").val();
        list[5] = $("#h").val();
        var currentPath = document.getElementById("currentPath").value;
        // 这里是利用的dwr框架直接调用后台方法,以及使用后台传回的值
           // 这个方法就是利用坐标宽高进行切图,事实上这时候的原图已经在服务器了,所以我们只需要知道他的相对路径,即currentPath
        ReleaseService.cutImage(list, currentPath,  function(value){
    
            document.getElementById("currentPath").value = value;
        }
       );
    
        var bgObj=document.getElementById("bgDiv");
        var msgObj=document.getElementById("cutImageDiv");
        bgObj.style.display = msgObj.style.display = "none";
        piso.cancelSelection();
        haveImage = 1;
        $('#msHaveImage').show();
        //$(".imgareaselect-outer").hide();
        //$(".imgareaselect-selection").parent().hide();
        
    }

    ReleaseService的cutImage方法:

       public String cutImage(int[] size, String path)  {
            int x1 = size[0];
            int x2 = size[1];
            int y1 = size[2];
            int y2 = size[3];
            int w = size[4];
            int h = size[5];
            if(w <= 0)
                w = 480;
            if(h<=0)
                h = 520;
            if(x1<0)
                x1 = 0;
            if(y1<0)
                y1 = 0;
            
            //File file = new File(request.getSession().getServletContext().getRealPath(path));
            
            path = path.substring(2);
            
            WebContext ctx = WebContextFactory.get();
            User user = (User)ctx.getSession().getAttribute("user");
            SimpleDateFormat df = new SimpleDateFormat(BusinessConstants.DATE_FORMAT);
            String file_ext = path.substring(path.lastIndexOf(BusinessConstants.DOT) + 1);
            File file = new File(ctx.getSession().getServletContext().getRealPath(path));
            String imageName = user.getId() + BusinessConstants.UNDERLINE + 
                df.format(new Date()) + BusinessConstants.DOT + file_ext;
            String newFile = ctx.getSession().getServletContext().getRealPath(BusinessConstants.TEMP_PICTURE_PATH + imageName);
            
    //切图操作
    ImageCut.abscut(ctx.getSession().getServletContext().getRealPath(path), newFile, x1, y1, w, h);
            return BusinessConstants.TEMP_RELATIVE_PICTURE_PATH + imageName;
        }

    来看一下截图方法:主要是Graphics2D的drawImage方法。

    public static void abscut(String srcImageFile,String desImageFile, int x, int y,int width, int height) {
             try {
                 Image img;
                 ImageFilter cropFilter;
                 File srcFile = new File(srcImageFile);
                 //String fileName = srcFile.getName();
                 String ext = getExtension(srcImageFile);
                 if(ext==null)ext="jpg";
                 // 读取源图像
                 BufferedImage bi = ImageIO.read(srcFile);
                 int srcWidth = bi.getWidth(); // 源图宽度
                 int srcHeight = bi.getHeight(); // 源图高度
                 if (srcWidth >= width && srcHeight >= height) {
                     BufferedImage tag;
                     Image image = bi.getScaledInstance(srcWidth, srcHeight,Image.SCALE_DEFAULT);
                     // 四个参数分别为图像起点坐标和宽高
                     // 即: CropImageFilter(int x,int y,int width,int height)
                     cropFilter = new CropImageFilter(x, y, width, height);
                     img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
                     int type = BufferedImage.TYPE_INT_RGB;
                     if("gif".equalsIgnoreCase(ext)||"png".equalsIgnoreCase(ext)){
                         type = BufferedImage.TYPE_INT_ARGB;
                     }
                     tag = new BufferedImage(width, height,type);
                     Graphics2D g = (Graphics2D)tag.getGraphics();
                         
                     g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                     g.drawImage(img, 0, 0, null); // 绘制剪切后的图
                     g.dispose();
    
                     ImageIO.write(tag,ext, new File(desImageFile));
                     srcFile.delete();//删除原图
                 }
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
         
         public static String getExtension(String srcImageFile) {
            String ext = null;
            if(srcImageFile!=null && srcImageFile.lastIndexOf(".")>-1){
                ext = srcImageFile.substring(srcImageFile.lastIndexOf(".")+1);
            }
            return ext;
        }    

      步骤3:

     至此,截图文件就被保存到指定的文件夹下,相对路径也会被存到数据库中,在页面上的处理就是把需要展现的img转变成src接可以完成了。

    补充: 因为以上的流程会导致零时文件夹的废弃文件(比如用户上传了原图,却放弃截图),座椅考虑在linux,上写一个定时脚本,来删除这个零时文件夹下的图片。

    一下是遗留问题,希望园子里的朋友能够给一点意见或提示:

     问题:

    1,使用imgareaselect的时候使用截图框固定的形式,如果原图比这个固定框小,就会出现js错误。是否解决方案?

    2,截图程序中利用Graphics2D的drawImage方法来画图,耗时过长,ajax效果的就要延迟体现,无法满足截图后马上显示效果。这个方面不知道怎么改进?

     好吧 我不理解园子的朋友指的图是不是这个,姑且认为是效果图吧

    上一张剪切图片时候的图片:

    有兴趣的帮我解答下我遗留的问题哦,谢啦。

     万水千山总是情,也许您可以支持一下,谢谢!

     

    让我们继续前行

    ----------------------------------------------------------------------

    努力不一定成功,但不努力肯定不会成功。
    共勉。

  • 相关阅读:
    用一条UPDATE语句交换两列的值
    js之事件冒泡和事件捕获详细介绍
    C# String与string的区别
    setTimeout()和setInterval()方法的区别?
    jQuery的.bind()、.live()和.delegate()之间区别
    在Hyper-V虚拟机中使用Wi-Fi上网
    调整框架的尺寸,是否显示滚动条,跳出框架
    调整框架的尺寸
    查看jquery绑定的事件函数
    Onload,Onunload,onbeforeunload,$(window).load(function() {})和$(document).ready(function(){})
  • 原文地址:https://www.cnblogs.com/killbug/p/2862179.html
Copyright © 2011-2022 走看看