【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的博客。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM