600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > js angularjs 图片上传服务器 并解决照片旋转问题 前端图片压缩上传

js angularjs 图片上传服务器 并解决照片旋转问题 前端图片压缩上传

时间:2019-03-18 10:43:43

相关推荐

js angularjs 图片上传服务器 并解决照片旋转问题 前端图片压缩上传

手机网站 App 开发时遇到用户拍照上传的场景,照片的大小一般不低于2M ,用户网络不好时会导致上传的时候异常卡顿,因此考虑使用前端图片压缩,再上传服务器.

主要使用canvas来重新绘制前端图片,然后使用toDataURL方法拿到图片被压缩之后的的 Base64 编码数据,上传编码数据,后台解码还原成图片,并根据前端传递的图片旋转信息将图片做相应的旋转处理,废话不多说,直接上代码,虽然说的是 angularjs 的压缩图片上传,其实跟 angularjs 基本没有关系纯粹的 js 代码实现的图片重绘:

前端主要代码

this.uploadPic = function(file, success, fail) {if (!/image\/\w+/.test(file.type)) {alert("image only please.");return false;}//EXIF为一个 js 读取图片参数工具类,可以用来读取照片被旋转的角度,//用作后端代码修正照片旋转,EXIF.getData(file,function() {//orient即读取到的照片旋转参数orient = EXIF.getTag(this,'Orientation');var rotate = 0;if (orient != null && orient != ""&& orient != 1) {switch (orient) {case 6:// 需要顺时针(向左)90度旋转rotate = 90;break;case 8:// 需要逆时针(向右)90度旋转rotate = 270;break;case 3:// 需要180度旋转rotate = 180;break;}}//此处开始读取图片并使用canvas将读取到的信息重新绘制var reader = new FileReader();reader.readAsDataURL(file);reader.onload = function(e) {var img = new Image, width = 640, // image// resizequality = 0.8, // image// qualitycanvas = document.createElement("canvas"), drawer = canvas.getContext("2d");img.src = this.result;img.onload = function() {canvas.width = width;canvas.height = width * (img.height / img.width);//开始绘制图片(压缩之后)drawer.drawImage(img, 0, 0,canvas.width,canvas.height);//获取压缩之后的 base64 编码的数据bodyData = canvas.toDataURL("image/jpeg",quality);//上传图片的 base64 编码信息$http.post("/common/upload-base64?rotate=" + rotate,bodyData).success(function(data) {success(data);}).error(function(data) {fail(data);});}}});}

在需要上传图片的地方调用uploadPic方法即可,file 传入 input.files[0] success 为上传成功之后的回调方法,fail 为上传失败之后的回调;

后端代码:

@RequestMapping(value = "/upload-base64", method = RequestMethod.POST)@ResponseBodypublic Map<String, Object> uploadFileBase64(HttpServletRequest request, HttpServletResponse response,@RequestBody String fileBase64,@RequestParam(required = false, value = "rotate", defaultValue = "0") int rotate) throws IOException {logger.info("开始上传base64格式的文件:");long begin = System.currentTimeMillis();//前端上传的数据的开始部分为文件标识信息,在解码之前需要去掉这部分信息fileBase64 = fileBase64.replace("data:image/jpeg;base64,", "");// Base64解码byte[] bytes = Base64.decodeBase64(fileBase64);for (int i = 0; i < bytes.length; ++i) {if (bytes[i] < 0) {// 调整异常数据bytes[i] += 256;}}String separator = "/";String realServerPath = request.getSession().getServletContext().getRealPath(separator);Date date = new Date();String dateStr = new SimpleDateFormat("yyyyMMdd").format(date);String timeStr = new SimpleDateFormat("HHmmssSSS").format(date);// 存储的相对路径, 用于返回到页面StringBuffer relativePath = new StringBuffer();relativePath.append(this.uploadPath).append(separator).append(dateStr);StringBuffer uploadDir = new StringBuffer();uploadDir.append(realServerPath).append(separator).append(relativePath);File dirPath = new File(uploadDir.toString());if (!dirPath.exists()) {dirPath.mkdirs();}StringBuffer savedFileName = new StringBuffer();savedFileName.append(dateStr).append(timeStr).append(new Random().nextInt()).append(".").append("jpg");String realFilePath = uploadDir + separator + savedFileName;File uploadedFile = new File(realFilePath);//写入图片FileCopyUtils.copy(bytes, uploadedFile);logger.info("上传base64文件成功:" + ",耗时:" + (System.currentTimeMillis() - begin) + "ms");//校验是否需要对图片做旋转处理if (ImageUtil.ANGLE_0 != rotate) {ImageUtil.rotatePhonePhoto(realFilePath, rotate);}Map<String, Object> map = new HashMap<>();map.put("relativePath", relativePath + separator + savedFileName);return map;}

旋转图片的代码如下:

/*** 将图片旋转一定角度** @param fullPath* @param angel* @return*/public static String rotatePhonePhoto(String fullPath, int angel) {logger.info("旋转图片:" + fullPath + " 角度:" + angel);long begin = System.currentTimeMillis();BufferedImage src;try {ImageIO.setUseCache(false);src = ImageIO.read(new File(fullPath));int src_width = src.getWidth(null);int src_height = src.getHeight(null);Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);BufferedImage res = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);Graphics2D g2 = res.createGraphics();g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);g2.rotate(Math.toRadians(angel), src_width / 2,src_height / 2);g2.drawImage(src, null, null);//注意此处使用 jpg 格式,如果使用其他格式编码会出现效率的诸多问题ImageIO.write(res, "jpg", new File(fullPath));} catch (IOException e) {logger.error("", e);}logger.info("旋转图片:" + fullPath + " 角度:" + angel + " 耗时:" + (System.currentTimeMillis() - begin) + "ms");return fullPath;}/*** 计算新照片的大小** @param src* @param angel* @return*/public static Rectangle calcRotatedSize(Rectangle src, int angel) {// if angel is greater than 90 degree, we need to do some conversionif (angel >= 90) {if (((angel / 90) % 2) == 1) {int temp = src.height;src.height = src.width;src.width = temp;}angel = angel % 90;}double r = Math.sqrt((src.height * src.height) + (src.width * src.width)) / 2;double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;double angel_dalta_width = Math.atan((double) src.height / src.width);double angel_dalta_height = Math.atan((double) src.width / src.height);int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));int des_width = src.width + (len_dalta_width * 2);int des_height = src.height + (len_dalta_height * 2);return new Rectangle(new Dimension(des_width, des_height));}

以上代码即可解决图片压缩上传,照片翻转的问题

如果想上传图片原图,并在后端做图片的选择操作,最好在后端直接读取图片,EXIF.js读取图片信息时非常慢,但由于图片重新绘制会丢失照片原有的旋转信息因此前端压缩时必须读取照片旋转角度以便后台修正,如果前端直接上传原图,可以在后台使用

<dependency><groupId>com.drewnoakes</groupId><artifactId>metadata-extractor</artifactId><version>2.10.1</version></dependency>

来读取照片信息,并获取需要旋转的角度

主要代码如下:

/*** 获取图片的旋转角度** @param filePath* @return 图片旋转角度*/public static int getRotateAngleForPhoto(String filePath) {File file = new File(filePath);int angle = ANGLE_0;Metadata metadata;try {metadata = JpegMetadataReader.readMetadata(file);Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);if ((null != directory) && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {// Exif信息中方向int orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);// 原图片的方向信息if (6 == orientation) {// 6旋转90angle = ANGLE_90;} else if (3 == orientation) {// 3旋转180angle = ANGLE_180;} else if (8 == orientation) {// 8旋转90angle = ANGLE_270;}}} catch (JpegProcessingException e) {logger.error("", e);} catch (MetadataException e) {logger.error("", e);} catch (IOException e) {logger.error("", e);}return angle;}

不压缩直接上传的前端代码如下,参数的意义与之前压缩上传的一致

this.uploadPicNotCompress = function(file, success, fail) {if (!/image\/\w+/.test(file.type)) {alert("image only please.");return false;}var formdata = new FormData(); // 初始化一个FormData实例formdata.append('file', file); // file就是图片或者其他你要上传的formdata$http.post("common/upload", formdata, {transformRequest : angular.identity,headers : {'Content-Type' : undefined}}).success(function(data) {success(data);}).error(function(data) {fail(data);});}

exif.js下载链接:/s/1jItDFMI 密码:m98m

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。