Jcrop插件+Canvas实现图片上传预览+图片裁剪上传
2017-12-09 09:16
791 查看
前言
想实现一个功能:用户点击上传按钮,选择图片后。图片显示在一个弹出框上,并可以对图片进行裁剪。裁剪后的图片显示在页面上。提交表单即可上传图片。遇到问题
浏览器的安全设置不让用户获取上传的图片路径,实际获取的是c:\fakepath\a.jpg(假设图片是c盘下的a.jpg)ajax如何异步上传图片?
Canvas画裁剪的图片时长宽不一样(本来想画100x100的图片,结果在画布上显示100x50)
Canvas上的图片怎么上传?
问题解决
选择图片后,触发input的onchange事件:发送异步请求将图片上传,返回图片的名称,然后弹框,将图片显示出来。将表单封装为FormData类型,ajax进行一些设置即可,具体百度有说。
设置Canvas宽高我用的是style:width:100px;height:100px;,后来直接写Canvas的属性width=100px height=100px,问题就解决了。具体原因百度有说。
获取Canvas的图片流(实际上就是一段字符串),表单提交图片流。后台用Base64解析图片流成为byte数组,然后根据byte数组创建输入流,有了输入流,就能够写出一张图片了。
部分代码
<!-- 图片上传,openPhotoCut的功能是异步上传图片,显示图片并裁剪 --> <form id="uploadForm" class="form-horizontal" role="form" enctype="multipart/form-data"> <div class="form-group namediv"> <label class="col-sm-2" for="photo" style="font-size: 15px;"><span style="color:red;"> </span>菜品图片</label> <div class="col-sm-6"> <input type="file" class="photo" id="photo" name="photo" onchange="openPhotoCut();" /> </div> </div> </form>
// 打开图片裁剪框 function openPhotoCut() { // ajax上传图片的关键 var formData = new FormData($("#uploadForm")); var fileName; // 上传文件名 // 在表单里面添加上传的图片 formData.append("photo", $(".photo").get(0).files[0]); // 上传未裁剪的图片 $.ajax({ type: "POST", url: "${pageContext.request.contextPath }/business/product/getFileLocationAjax", async: false, data: formData, // 以下两行不写可能会报错 contentType: false, processData: false, success: function(result) { // 得到图片名称 fileName = result; alert(fileName); } }); // 这里使用的是layer弹框插件,弹出图片裁剪框,显示上传的图片,并进行裁剪 layer.open({ title: '图片裁剪', type: 1, skin: 'layui-layer-rim', //加上边框 area: ['600px', '500px'], //宽高 // 这里纯粹是html内容,cutAndShow的功能是把刚才上传的图片删除,然后把裁剪的图片显示在Canvas上,并保存图片流在input中。 content: '<img id="prephoto" src="${pageContext.request.contextPath }/uploads/' + fileName + '"/>' + '<button class="btn btn-primary" style="margin: 20px;" onclick="cutAndShow(\'' + fileName + '\');">裁剪</button>' + 'x轴:<input type="text" readonly id="x" name="x" value="0" style="width: 50px;" /> ' + 'y轴:<input type="text" readonly id="y" name="y" value="0" style="width: 50px;" /> ' + '长度:<input type="text" readonly id="w" name="w" value="0" style="width: 50px;" /> ' + '宽度:<input type="text" readonly id="h" name="h" value="0" style="width: 50px;" /> ' }); // 裁剪插件 $("#prephoto").Jcrop({ minSize: [ 80, 80 ], // 最小尺寸 aspectRatio: 1, // 等宽高 onSelect: updateCoords }); } // 及时更新裁剪区域坐标和尺寸 function updateCoords(c) { $('#x').val(c.x); $('#y').val(c.y); $('#w').val(c.w); $('#h').val(c.h); }; // 裁剪图片并显示在画布 function cutAndShow(fileName) { // 删除未裁剪的图片 $.ajax({ type: "POST", url: "${pageContext.request.contextPath }/business/product/deleteImageAjax", async: false, data: {"fileName": fileName}, success: function(result) { } }); var x = $("#x").val(); var y = $("#y").val(); var w = $("#w").val(); var h = $("#h").val(); if (x == 0 || y == 0 || w == 0 || h == 0) { alert("请裁剪图像"); } var img = document.getElementById("prephoto"); var c=document.getElementById("oldConvas"); var ctx = c.getContext("2d"); ctx.drawImage(img, x, y, w, h,0,0,100,100); // 画出图片,尺寸100x100 var newImg = c.toDataURL("image/jpeg"); // 获得图片流 $(".photoStream").val(newImg); // 将图片字符流存储在input中 layer.closeAll(); // 关闭所有窗口 }
<!-- 这是另一个表单,用来上传图片和其他内容 --> <form class="form-horizontal" role="form" method="post" onsubmit="return validate();" action="${pageContext.request.contextPath }/business/product/add.action"> <!-- 裁剪后的图片 --> <div class="form-group namediv"> <label class="col-sm-2" for="name" style="font-size: 15px;"></label> <div class="col-sm-6"> <span class="text text-danger">上传图片要求:格式jpg/jpeg/png/gif/bmp,大小<=2m,尺寸<=500x500,裁剪后图片尺寸为100x100</span> <div style="width: 100px; height: 100px; border: 1px solid black;"><canvas id="oldConvas" width="100px" height="100px"></canvas></div> <input type="hidden" class="photoStream" id="photoStream" name="photoStream" /> </div> </div> <!-- 其他表单内容,不写了 --> </form>
/** * 异步上传图片并返回图片名称 * @param model * @param request * @param response * @param file 上传的图片 * @throws Exception */ @RequestMapping(value="getFileLocationAjax",method=RequestMethod.POST) public void getFileLocationAjax(Model model, HttpServletRequest request, HttpServletResponse response, @RequestParam("photo") CommonsMultipartFile file) throws Exception { if (!file.isEmpty()) { InputStream in = file.getInputStream(); String fileName = saveImage(request, in); // 调用保存图片方法 // 保存图片名,方便剪切后删除 model.addAttribute("fileName", fileName); response.setContentType("html/text; charset=UTF-8"); PrintWriter writer = response.getWriter(); writer.print(fileName); } } /** * 保存图片到上传路径的方法 * @param request * @param in 图片输入流 * @throws Exception * @return 返回文件名 */ public String saveImage(HttpServletRequest request, InputStream in) throws Exception { String fileName = UUIDUtils.getUUID() + ".jpg"; // 随机文件名 String savePath = request.getSession().getServletContext().getRealPath("/WEB-INF/uploads") + "/"; // 获得保存路径 File f = new File(savePath); if (!f.exists()) { f.mkdirs(); } FileOutputStream fos = new FileOutputStream(savePath + fileName); int b = 0; while ((b = in.read()) != -1) { fos.write(b); } fos.close(); in.close(); return fileName; }
/** * 异步删除上传的文件 * @param response * @param request * @param fileName 文件名 * @throws Exception */ @RequestMapping(value="/deleteImageAjax") public void deleteImageAjax(HttpServletRequest request, String fileName) throws Exception { System.out.println("图片名为:" + fileName); String savePath = request.getSession().getServletContext().getRealPath("/WEB-INF/uploads") + "/"; // 获得保存路径 File file = new File(savePath + fileName); boolean flag = false; if (!file.exists()) { System.out.println("文件不存在,无法删除"); } else { if (file.isFile()) { flag = file.delete(); } } }
/** * 根据图片流保存图片 * @param request * @param data 图片流 * @throws Exception * @return 图片名称 */ public String saveImageByStrem(HttpServletRequest request, String data) throws Exception { Base64 base64 = new Base64(); // 获得图片流,实际图片数据从data:image/jpeg;base64开始 byte[] b = base64.decodeBase64(data.substring("data:image/jpeg;base64,".length())); InputStream in = new ByteArrayInputStream(b); String fileName = saveImage(request, in); // 保存图片 return fileName; }
心得
前端插件满天飞,经常造成选择困难症。遇到一个插件,觉得难用就放弃了,换一个插件,还是嫌麻烦,又换一个,结果进入了一个死循环。既浪费时间,又影响心情。插件是来简便开发的,不是来折腾的!相关文章推荐
- jQuery插件jcrop+Fileapi完美实现图片上传+裁剪+预览的代码分享
- ASP.NET使用Jcrop插件实现图片上传裁剪功能
- html Jcrop+canvas实现前端裁剪图片,并上传到服务器
- JQuery 图像裁剪插件Jcrop实现图片上传功能(mysql DB)
- h5 canvas实现图片裁剪上传
- Jcrop+uploadify+php实现上传头像预览裁剪
- jquery.uploadify插件实现图片上传和预览效果
- 上传、裁剪图片-----Jcrop图片裁剪插件
- Jcrop+uploadify+php实现上传头像预览裁剪
- 利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
- H5实现图片预览、裁剪、批量上传
- java实现图片处理之Jcrop 图像裁剪插件
- springMVC结合Jcrop实现头像上传裁剪预览功能
- jquery.uploadify插件实现图片上传和预览效果
- php+js实现图片的上传、裁剪、预览、提交示例
- php+js实现图片的上传、裁剪、预览、提交示例
- 基于Jcrop的图片上传裁剪加预览
- 使用Jcrop插件裁剪图片并上传(Spring MVC)
- php+js实现图片的上传、裁剪、预览、提交示例
- jquery.Jcrop结合JAVA后台实现图片裁剪上传实例