上傳文件方面:
一、前端
使用的是jQuery框架來上傳圖片,參考的是harttle大神博客:http://harttle.com/2016/07/04/jquery-file-upload.html,利用formdata來封裝圖片傳到后台,代碼如下:
$('button').click(function(){ var files = $('#avatar').prop('files'); var data = new FormData(); data.append('avatar', files[0]); $.ajax({ url: '/api/upload', type: 'POST', data: data, cache: false, processData: false, contentType: false }); });
二、后端
采用的是SpringMVC框架,在讀取這個formdata時比較頭疼,不知道怎么讀,通過搜索發現有人用了MultipartHttpServletRequest這樣一樣請求類來讀上傳的formdata內容,不禁感慨這么多類我要用到什么時候才能熟練掌握,參考鏈接:
http://www.tuicool.com/articles/2EnMBz
@RequestMapping(value = "/upload") public@ResponseBody String upload(MultipartHttpServletRequest request) throws Exception { Iterator<String> itr = request.getFileNames(); MultipartFile mpf = request.getFile(itr.next()); ufile = new UploadedFile(mpf.getBytes(), mpf.getOriginalFilename(), mpf.getContentType(), mpf.getBytes().length); String name = "default"; String type = "jpg"; if (ufile.name.contains(".")) { String[] names = ufile.name.split("\\."); name = names[0]; type = names[1]; } String imagePath = "http://" + request.getServerName() + ":" + request.getServerPort() + "/user/image/" + name + "/" + type; return imagePath; }
其中這個UploadedFile是自己定義的一個封裝內部類,代碼:
private class UploadedFile { byte[] bytes; int length; String type; String name; public UploadedFile() { } public UploadedFile(byte[] bytes, String name, String type, int length) { this.bytes = bytes; this.name = name; this.type = type; this.length = length; File file = new File(Constant.IMGDIR + name); if (file.exists()) { file.delete(); } FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(file); fileOutputStream.write(this.bytes, 0, this.length); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
MultipartHttpServletRequest這個類可以獲取上傳文件的字節流getBytes(),文件名getOriginalFilename(),文件類型getContentType()等信息。
本來想將圖片文件名作為參數返回到鏈接中,但是發現在讀取時會從"."分割,所以自己就想辦法把圖片的文件名分成兩部分,在以"."分割時還報了個錯,原因是java以"."分割時要寫成split("\\.")。
讀取圖片方面
本來想偷懶直接用之前寫過的代碼:http://www.cnblogs.com/puyangsky/p/5390263.html
初始代碼如下:
@RequestMapping(value = "/image/{name}/{type}", method = RequestMethod.GET) public void getImage(@PathVariable String name, @PathVariable String type, HttpServletResponse response) throws IOException{ InputStream inputStream = null; OutputStream out = null; try { File file = new File("D:\\image\\" + name + "." + type); inputStream = new FileInputStream(file); out = response.getOutputStream(); // pic size = 1M byte[] bytes = new byte[5 * 1024 * 1024]; int len = 0; while ((len = inputStream.read(bytes)) > 0) { out.write(bytes, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { if (inputStream != null) inputStream.close(); if (out != null) out.close(); } }
直接利用java IO來讀取圖片,並將字節流寫到response的outputstream中。
在windows上測試完美通過,但是放到linux服務器上之后每次讀取圖片都會報錯,錯誤是java.net.socketexception:broken pipe,錯誤定位就在這個getImage方法中。
果斷懵逼,沒遇過這樣的問題,一番搜索后,看到這樣一個帖子:http://bbs.csdn.net/topics/390360405
在里面有人說要用java的NIO來實現,繼續懵逼,NIO又是什么,無所謂先把bug解決了再好好了解,繼續搜索發現有一個ImageIO的包是使用了NIO實現的,修改代碼,完美解決問題,最后的getImage方法的代碼如下:
@RequestMapping(value = "/image/{name}/{type}", method = RequestMethod.GET) public void getImage(@PathVariable String name, @PathVariable String type, HttpServletResponse response) throws IOException{ OutputStream out = null; BufferedImage image = null; try { File file = new File(Constant.IMGDIR + name + "." + type); image = ImageIO.read(file); out = response.getOutputStream(); ImageIO.write(image, type, out); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) out.close(); } }
而且ImageIO的方法封裝的非常好,直接三行把圖片輸出到response的輸出流中。
感想
java中的細節太多,一方面是需要慢慢積累,另一方面基礎知識也要打好,感覺自己連java IO都沒弄熟悉,碰到什么NIO就更一臉蒙蔽了,之后也會寫一些記錄學習IO和NIO的博客。