通用的下载文件服务

目录

方式一:基于传统的IO

方式二:基于NIO实现文件的下载 - Channle组件及其API来实现!


内容:本质上仍然是基于Java的IO(特别是File IO)流实现文件的读与写(只不过这个时候的写是往浏览器”写")

方式一:基于传统的IO

Controller层-得到附件对象,拼接完整文件的路径,将文件转化为输入流写入response对象之中

    //下载文件
    @RequestMapping(value = "file/download/{id}", method=RequestMethod.GET)
    @ResponseBody
    public String addItemAndUpload(@PathVariable Integer id, HttpServletResponse response){
        if(id == null || id <= 0){
            return null;
        }
        try{
            Appendix appendix = itemService.getAppendixUrl(id);
            String fileUrl = env.getProperty("file.upload.location.root.url") + appendix.getFileUrl();
            System.out.println("appendixName:" + appendix.getName());
            FileInputStream is = new FileInputStream(fileUrl);
            commonService.downloadFile(response, is, appendix.getName());

            return appendix.getName();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

CommonService层-循环读写

    public void downloadFile(HttpServletResponse response, InputStream is, final String fileName) throws Exception{
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try{
            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(response.getOutputStream());

            //设置相应类型和响应头
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename="+new String(fileName.getBytes("utf-8"), "iso-8859-1"));

            //TODO:其实就是一个不断读、写的过程
            byte[] buffer = new byte[10240];
            int len = bis.read(buffer);
            while(len != -1){
                bos.write(buffer, 0, len);
                len = bis.read(buffer);
            }
            bos.flush();
        }finally {
            if(bis != null){
                bis.close();
            }
            if(bos != null){
                bos.close();
            }
            if(is != null){
                is.close();
            }
        }
    }

方式二:基于NIO实现文件的下载 - Channle组件及其API来实现!

本质:仍然是读取待下载的文件,转化为输入流,通过Channel复制到输出流,最终写回浏览器的响应对象中(只不过中间的整个过程是非阻塞式的)

    public void downloadFileV2(HttpServletResponse response, FileInputStream is, final String fileName) throws Exception{
            //设置相应类型和响应头

        response.setContentType("application/octet-stream;charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename="+new String(fileName.getBytes("utf-8"), "iso-8859-1"));

        int bufferSize=10240;
        byte[] byteArr = new byte[bufferSize];
        FileChannel fileChannel = is.getChannel();
        ByteBuffer buffer = ByteBuffer.allocateDirect(61440);
        try{

            int nRead;
            int nGet;
            while((nRead=fileChannel.read(buffer)) != -1){
                if(nRead == 0){
                    continue;
                }

                buffer.position(0);
                buffer.limit(nRead);
                while (buffer.hasRemaining()){
                    nGet = Math.min(buffer.remaining(), bufferSize);

                    //TODO: 从磁盘中读I - Input
                    buffer.get(byteArr, 0, nGet);
                    //TODO: 往浏览器响应流写O - Output
                    response.getOutputStream().write(byteArr);
                }
                buffer.clear();
            }

        }finally {
            buffer.clear();
            fileChannel.close();
            is.close();
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值