赞
踩
cropper是一款用于图像裁剪的插件,可以实现对本地用户上传到服务器的图片裁剪,比如用户上传个人头像,博客首图等应用.
只需要在前端引入对应的cropper的css和js即可,th:href是springboot官方推荐的thymleaf中的语法
cropper的css和js文件下载: cropper插件下载
thymleaf文档地址: thymleaf 官方文档
<link rel="stylesheet" href="../static/css/cropper.min.css" th:href="@{/css/cropper.min.css}">
<link rel="stylesheet" href="../static/css/ImgCropping.css" th:href="@{/css/ImgCropping.css}">
<script src="../static/js/jquery-3.5.1.min.js" th:src="@{/js/jquery-3.5.1.min.js}"></script>
<script src="../static/js/cropper.min.js" th:src="@{/js/cropper.min.js}"></script>
这个问题耗了博主一个上午才解决,害
1.在head标签中加上下面两行代码,
<!--禁用这两个-->
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
2.在script标签中加上下面代码,
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
解决: 扩展SpringMVC,添加资源映射路径即可
package com.itguigu.learn.config; import org.springframework.stereotype.Component; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * 配置静态资源映射 **/ @Component public class WebMvcConfig implements WebMvcConfigurer { /** * 添加静态资源文件,外部可以直接访问地址 * * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); } }
注释都在代码中,根据个人的controller请求地址修改ajax中的调用地址即可
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>基于cropper.js的图片裁剪</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="format-detection" content="telephone=no"> <link rel="stylesheet" href="../static/css/cropper.min.css" th:href="@{/css/cropper.min.css}"> <link rel="stylesheet" href="../static/css/ImgCropping.css" th:href="@{/css/ImgCropping.css}"> <!--禁用这两个--> <meta name="_csrf" th:content="${_csrf.token}"/> <meta name="_csrf_header" th:content="${_csrf.headerName}"/> <style> .str { width: 150px; height: 200px; border: solid 1px #e3e3e3; padding: 5px; margin-top: 10px } </style> </head> <body> <label title="上传图片" for="chooseImg" class="l-btn choose-btn"> <input type="file" accept="image/jpg,image/jpeg,image/png" name="file" id="chooseImg" class="hidden" onchange="selectImg(this)" /> 选择图片 </label> <div class="str"> <img id="finalImg" src="" width="100%"> </div> <!--图片裁剪框 start--> <div style="display: none" class="tailoring-container"> <div class="black-cloth" onclick="closeTailor(this)"></div> <div class="tailoring-content"> <div class="tailoring-content-one"> <div class="close-tailoring" onclick="closeTailor(this)">×</div> </div> <div class="tailoring-content-two"> <div class="tailoring-box-parcel"> <img id="tailoringImg"> </div> <div class="preview-box-parcel"> <p>图片预览:</p> <div class="square previewImg"></div> <!-- <div class="circular previewImg"></div>--> </div> </div> <div class="tailoring-content-three"> <button class="l-btn cropper-reset-btn">复位</button> <button class="l-btn cropper-rotate-btn">旋转</button> <button class="l-btn cropper-scaleX-btn">换向</button> <button class="l-btn sureCut" id="sureCut">确定</button> </div> </div> </div> <button class="l-btn layui-btn-warm" id="test">测试</button> <!--图片裁剪框 end--> <!--<script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>--> <script src="../static/js/jquery-3.5.1.min.js" th:src="@{/js/jquery-3.5.1.min.js}"></script> <script src="../static/js/cropper.min.js" th:src="@{/js/cropper.min.js}"></script> <script type="text/javascript"> //弹出框水平垂直居中 var token = $("meta[name='_csrf']").attr("content"); var header = $("meta[name='_csrf_header']").attr("content"); $(document).ajaxSend(function(e, xhr, options) { xhr.setRequestHeader(header, token); }); (window.onresize = function() { var win_height = $(window).height(); var win_width = $(window).width(); if (win_width <= 768) { $(".tailoring-content").css( { "top" : (win_height - $(".tailoring-content") .outerHeight()) / 2, "left" : 0 }); } else { $(".tailoring-content").css( { "top" : (win_height - $(".tailoring-content") .outerHeight()) / 2, "left" : (win_width - $(".tailoring-content") .outerWidth()) / 2 }); } })(); // 选择文件触发事件 function selectImg(file) { //文件为空,返回 if (!file.files || !file.files[0]) { return; } $(".tailoring-container").toggle(); var reader = new FileReader(); reader.onload = function(evt) { var replaceSrc = evt.target.result; // 更换cropper的图片 $('#tailoringImg').cropper('replace', replaceSrc, false);// 默认false,适应高度,不失真 } reader.readAsDataURL(file.files[0]); } // cropper图片裁剪 $('#tailoringImg').cropper({ aspectRatio : 1 / 1,// 默认比例 preview : '.previewImg',// 预览视图 guides : false, // 裁剪框的虚线(九宫格) autoCropArea : 0.5, // 0-1之间的数值,定义自动剪裁区域的大小,默认0.8 movable : false, // 是否允许移动图片 dragCrop : true, // 是否允许移除当前的剪裁框,并通过拖动来新建一个剪裁框区域 movable : true, // 是否允许移动剪裁框 resizable : true, // 是否允许改变裁剪框的大小 zoomable : false, // 是否允许缩放图片大小 mouseWheelZoom : false, // 是否允许通过鼠标滚轮来缩放图片 touchDragZoom : true, // 是否允许通过触摸移动来缩放图片 rotatable : true, // 是否允许旋转图片 crop : function(e) { // 输出结果数据裁剪图像。 } }); // 旋转 $(".cropper-rotate-btn").on("click", function() { $('#tailoringImg').cropper("rotate", 45); }); // 复位 $(".cropper-reset-btn").on("click", function() { $('#tailoringImg').cropper("reset"); }); // 换向 var flagX = true; $(".cropper-scaleX-btn").on("click", function() { if (flagX) { $('#tailoringImg').cropper("scaleX", -1); flagX = false; } else { $('#tailoringImg').cropper("scaleX", 1); flagX = true; } flagX != flagX; }); // 确定按钮点击事件 $("#sureCut").on("click", function() { if ($("#tailoringImg").attr("src") == null) { return false; } else { var cas = $('#tailoringImg').cropper('getCroppedCanvas');// 获取被裁剪后的canvas var base64 = cas.toDataURL('image/jpeg'); // 转换为base64 $("#finalImg").prop("src", base64);// 显示图片 uploadFile(base64)//编码后上传服务器 closeTailor();// 关闭裁剪框 } return false; }); // 关闭裁剪框 function closeTailor() { $(".tailoring-container").toggle(); } $('#test').on("click",function () { if ($("#tailoringImg").attr("src") == null) { return false; } else { var cas = $('#tailoringImg').cropper('getCroppedCanvas');// 获取被裁剪后的canvas var base64 = cas.toDataURL('image/jpeg'); // 转换为base64 $("#finalImg").prop("src", base64);// 显示图片 uploadFile(encodeURIComponent(base64))//编码后上传服务器 closeTailor();// 关闭裁剪框 } // $.ajax({ // url: 'http://localhost:8080/testAjax', // type: 'POST', // data:"base64url="+12345, // dataType: "json", // success:function (data) { // alert(12); // }, // error:function (data) { // alert(34); // } // }) }) //ajax请求上传 function uploadFile(file) { let fileName = $('#chooseImg')[0].files[0].name; $.ajax({ url : '/upload', type : 'POST', //data : "file=" + file, data:{ "file":file, "fileName":fileName }, dataType: 'json', async : true, success : function(data) { console.log(data) }, error: function (data) { console.log(data); } }); return false; } </script> </body> </html>
说明: 上传的文件可以保存在自定义的文件目录中,这里博主保存到了下图的位置
代码
package com.itguigu.learn.controller; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.springframework.stereotype.Controller; import org.springframework.util.ClassUtils; import org.springframework.web.bind.annotation.*; import sun.misc.BASE64Decoder; @Controller @RequestMapping("/upload") public class Cropper { /** * @Param(file: 前台传过来的base64编码字符串) * @Param(fileName: 前台传过来的文件名) * @Author: rjc */ @RequestMapping @ResponseBody public String cropper(@RequestParam("file") String file, @RequestParam("fileName") String fileName) throws Exception { decodeBase64String_(file,fileName); return "success"; } public void decodeBase64String_(String base64,String fileName) throws IOException { // dir = "/target/static/images/" String dir = ClassUtils.getDefaultClassLoader().getResource("static/images").getPath(); File file = new File(dir); if(!file.exists()){ file.mkdir(); } BASE64Decoder decoder = new BASE64Decoder(); String baseValue = base64.replaceAll(" ","+"); byte[] b = decoder.decodeBuffer(baseValue.replace("data:image/jpeg;base64,","")); base64 = base64.replace("base64",""); for(int i = 0;i<b.length;i++){ if(b[i]<0){ //调整异常数据 b[i]+=256; } } //生成jpeg图片 OutputStream out = new FileOutputStream(dir+"/"+fileName); out.write(b); out.flush(); out.close(); } }
写前端不难,但是更耗时间,很多玄学Bug,其实是对html和css和ajax的基础不扎实,学习Java后端的同时,需要多写写前端,巩固好基础
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。