SpringBoot 文件下载、分片下载

普通下载功能的实现

    FileInputStream inputStream = null;
    ServletOutputStream os = null;
    try {
        inputStream = new FileInputStream(file);

        //设置响应状态200
        response.setStatus(HttpServletResponse.SC_OK);
        //设置内容类型
        response.setContentType(getContentType(fileId));
        //添加响应头 设置内容长度
        response.addHeader("Content-Length", String.valueOf(file.length()));
        //添加响应头 设置允许浏览器可尝试恢复中断的下载
        response.addHeader("Accept-Ranges", "bytes");
        response.addHeader("Cache-control", "private");
        //添加响应头 设置浏览器另存为对话框的默认文件名
        response.addHeader("Content-Disposition", "filename=" + file.getName());
        response.addHeader("Last-Modified", new SimpleDateFormat("EEE, d MMM yyyy hh:mm:ss Z", Locale.ENGLISH).format(file.lastModified()) + " GMT");

        os = response.getOutputStream();

        byte[] buf = new byte[1024];
        int len;
        while ((len = inputStream.read(buf)) != -1) {
            os.write(buf, 0, len);
            os.flush();
        }
    } catch (Exception e) {
        //操作文件失败时返回响应状态 500
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    } finally {
        //结束后释放资源
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

支持分片下载功能的实现

  • 这里是因为测试中ios safari 浏览器无法正常打开播放视频文件,通过抓取分析浏览器访问静态资源视频过程实现的代码
    //获取请求头
    String range = request.getHeader("range");
    String referer = request.getHeader("referer");
    //处理range 计算请求的哪部分数据
    String[] split = range.split("bytes=|-");
    long begin = 0;
    if (split.length >= 2) {
        begin = Long.valueOf(split[1]);
    }
    long end = file.length() - 1;
    if (split.length >= 3) {
        end = Long.valueOf(split[2]);
    }
    long len = (end - begin) + 1;
    //如果请求的文件长度超过文件实际长度 返回错误状态
    if (end > file.length()) {
        //返回状态 500
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    }

    FileInputStream inputStream = null;
    ServletOutputStream os = null;
    try {
        //创建文件流
        inputStream = new FileInputStream(file);
        //将指针移到请求片段的开始位置
        inputStream.skip(begin);
        //设置响应状态 206 部分内容
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
        //设置内容类型
        response.setContentType(getContentType(fileId));
        //添加响应头 设置片段开始位置 结束位置 文件总长度
        response.addHeader("Content-Range", "bytes " + begin + "-" + end + "/" + file.length());
        //添加响应头 设置响应片段的长度
        response.addHeader("Content-Length", String.valueOf(len));
        //添加响应头 设置允许浏览器可尝试恢复中断的下载
        response.addHeader("Accept-Ranges", "bytes");
        response.addHeader("Cache-control", "private");
        //添加响应头 设置浏览器另存为对话框的默认文件名
        response.addHeader("Content-Disposition", "filename=" + file.getName());
        response.addHeader("Last-Modified", new SimpleDateFormat("EEE, d MMM yyyy hh:mm:ss Z", Locale.ENGLISH).format(file.lastModified()) + " GMT");

        os = response.getOutputStream();
        //从文件流中读指定长度的片段输出
        byte[] buf = new byte[1024];
        while (len > 0) {
            inputStream.read(buf);
            long l = len > 1024 ? 1024 : len;
            os.write(buf, 0, (int) l);
            os.flush();
            len -= l;
        }
    } catch (Exception e) {
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    } finally {
        //释放资源
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 昨天在例会上,做了一件错的事情,再次看到自己在某些事情上思维的混乱,看到自己的急躁,看到自己有限的包容心,看到自己...
    韩彦芳阅读 1,315评论 0 2
  • 进入了大学,我们肯定会遇到很多事情,课程压力,学业压力,社团,考证,培训…… 好多好多事情,有时候你会...
    想当个咸鱼阅读 1,657评论 -1 2
  • hello,我叫冯后莲,大家都叫我阿莲!今天我给大家讲讲我的经历!我是重庆永川人,土生土长的农村妹儿!我没有...
    冯后莲阅读 4,266评论 6 16
  • 休息十点多才起来吃早餐,吃完早餐看了一会书十二点多又去吃午饭,吃完饭看了一会书感觉看不进去了,看了一会电视说等下去...
    o蛋挞o阅读 1,558评论 0 5

友情链接更多精彩内容