当前位置: 首页 > article >正文

[实用小代码java]-如何将对象存储服务器上的文件下载到客户端

本文依据作者实际工作经历,介绍了如何在非主R的项目里添加一个文件下载工具类的过程,希望能对您有所启发。

1 交待一下背景

最近要在团队其他同学主R的一个项目里添加一个页面,该页面会有一个文件下载的功能。

调研后发现:

  • 该项目的后端代码没有类似的工具类

由于该项目不是我负责的小组主R,所以不想实现的太重(例如不想通过引入hutool工具包的方式来搞)

  • 要下载的文件存储于公司自研的对象存储服务器上
  • 可以拿到文件存储的URL,但该URL只可以在内网访问
  • 也可以通过公司自研对象存储服务器提供的SDK获取到存储文件对应的流文件(更安全)

2 前置知识

2.1 下载文件所需的响应头

application/octet-stream

可参考文章:
https://juejin.cn/post/7211401380770349115

2.2 java文件下载所需知识

其实这个很简单,相信很多初学java的都知道,就是将输入流(InputStream)拷贝到输出流(OutputStream)。

3 内部系统可行方案

考虑到文件存储对应的URL只可以在内网访问,所以不会将URL直接塞给客户端,而是后端服务读取URL,将其转为流,再输出到客户端。因此最初的实现方案如下:

/***
 *
 * @param fileName 文件名
 * @param filePath 文件路径 -- 往往该路径只能在内部系统使用,外网访问会失败
 * @param response
 * @throws IOException
 */
public static void downloadFile(String fileName, String filePath,
        HttpServletResponse response) throws IOException {

    //设置响应头:我不知道这个传输过来的东西是什么,
    //把它存储为一个文件,文件名叫做fileName(如x1.pdf,x2.ppt)
    response.setHeader("Content-Disposition", "attachment;filename="
            + URLEncoder.encode(fileName, "UTF-8"));
    response.setContentType("application/octet-stream");

    ServletOutputStream outputStream = null;
    InputStream inputStream = null;
    try {
        URL url = new URL(filePath);
        inputStream = url.openStream();
        outputStream = response.getOutputStream();

        IOUtils.copy(inputStream, outputStream);
        outputStream.close();
    } catch (IOException ioException) {
        throw new RuntimeException(ioException);
    } finally {
        if (inputStream != null) {
            inputStream.close();
        }
        if (outputStream != null) {
            outputStream.flush();
        }
    }
}

该方案在staging环境运行正常,但将其推到prt环境进行测试时会报403异常authority forbidden提示。

也就是说在prt或prod环境,服务端也无法通过URL来读取到相应的文件。

进一步验证:进入staging环境,去ping相应环境对应URL的域名可以ping通,但是在prt和prod却都无法ping通。

因此,该方案无法应用到线上。

4 通用方案

回看一下第3节对应的方案,其实下面这段代码的目的就是要获取一个输入流

URL url = new URL(filePath);
inputStream = url.openStream();
outputStream = response.getOutputStream();

而对象存储服务器提供的SDK可以安全地获取到存储文件对应的流文件,因此完全可以用其SDK来获取该流。

于是下载文件的方案就变成了如下更通用的方式:

/***
 * @param fileName 文件名
 * @param inputStream 文件流通过文件存储服务器对应SDK获取
 * @param response
 * @throws IOException
 */
public void downloadFile2(String fileName, InputStream inputStream,
        HttpServletResponse response) throws IOException {

    //设置响应头:我不知道这个传输过来的东西是什么,
    //把它存储为一个文件,文件名叫做fileName(如x1.pdf,x2.ppt)
    response.setHeader("Content-Disposition", "attachment;filename="
            + URLEncoder.encode(fileName, "UTF-8"));
    response.setContentType("application/octet-stream");

    ServletOutputStream outputStream = null;
    try {
        outputStream = response.getOutputStream();
        IOUtils.copy(inputStream, outputStream);
        outputStream.close();
    } catch (IOException ioException) {
        throw new RuntimeException(ioException);
    } finally {
        if (inputStream != null) {
            inputStream.close();
        }
        if (outputStream != null) {
            outputStream.flush();
        }
    }
}

http://www.kler.cn/a/391922.html

相关文章:

  • 性能优化、安全
  • 深入理解接口测试:实用指南与最佳实践5.0(三)
  • 【算法】——二分查找合集
  • C# 委托与匿名方法
  • 多叉树笔记
  • 物理设备命名规则(Linux网络服务器 15)
  • 书生浦语XTuner 微调个人小助手
  • 深入了解Git、GitHub、GitLab及其应用技巧
  • SpringBoot中的线程安全及其处理方法
  • SQL的基本CRUD操作
  • 方法论-批判性思维提问法
  • Nginx 部署负载均衡服务全解析
  • HCIP(11)-期中综合实验(BGP、Peer、OSPF、VLAN、IP、Route-Policy)
  • 博弈连锁美业门店管理系统中如何购买课程服务?美业疗愈系统收银系统源码
  • 四期书生大模型实战营(【基础岛】- 第1关 | 书生·浦语大模型开源开放体系)
  • spring cloud 入门笔记1(RestTemplate,Consul)
  • 全面介绍软件安全测试分类,安全测试方法、安全防护技术、安全测试流程
  • 安装阿里巴巴的Dragonwell(替代JDK)
  • [CKS] CIS基准测试,修复kubelet和etcd不安全项
  • hhdb数据库介绍(9-3)
  • 【论文笔记】SparseRadNet: Sparse Perception Neural Network on Subsampled Radar Data
  • [HarmonyOS]简单说一下鸿蒙架构
  • python数据写入excel文件
  • 【前端】Svelte:部署与快速开始
  • 推荐一款强大的图像处理软件:Adobe Photoshop2025
  • ReactPress技术揭秘