【java NIO】服务器端读写图片的一次排错经历
上传文件方面:
一、前端
使用的是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的博客。

浙公网安备 33010602011771号