zoukankan      html  css  js  c++  java
  • 【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的博客。

  • 相关阅读:
    5步教你完成小熊派开发板贴片
    了解JS压缩图片,这一篇就够了
    【华为云推官招募】加入云推官,月入8万的兼职不是梦
    JavaScript中的正则表达式详解
    一瓶可乐的自动售货机指令“旅程”
    年近而立,Java何去何从?
    数据平台、大数据平台、数据中台……你确定能分得清吗?
    微软看上的Rust 语言,安全性真的很可靠吗
    云图说丨手把手教你为容器应用配置弹性伸缩策略
    Spark优化之小文件是否需要合并?
  • 原文地址:https://www.cnblogs.com/puyangsky/p/5684503.html
Copyright © 2011-2022 走看看