Forest Forest
💒 首页
  • v1.5.30
  • v1.5.28
  • 🎄 ForestX
🌰 案例
💖 支持
🛫 更新记录
🧢 开发团队
⚒️ 参与贡献
  • MaxKey - 业界领先的身份管理和认证产品 (opens new window)
  • Snowy - 国内首个国密前后端分离快速开发平台 (opens new window)
  • Eoapi - 一个开源、可拓展的 API 工具平台 (opens new window)
  • Gitee (opens new window)
  • Github (opens new window)
💒 首页
  • v1.5.30
  • v1.5.28
  • 🎄 ForestX
🌰 案例
💖 支持
🛫 更新记录
🧢 开发团队
⚒️ 参与贡献
  • MaxKey - 业界领先的身份管理和认证产品 (opens new window)
  • Snowy - 国内首个国密前后端分离快速开发平台 (opens new window)
  • Eoapi - 一个开源、可拓展的 API 工具平台 (opens new window)
  • Gitee (opens new window)
  • Github (opens new window)
  • 序言

    • 🎁 新手介绍
    • 📖 文档
    • 🌰 使用案例
    • 🕵️‍ 关于作者
    • 👨‍🎓 贡献者列表
  • 入门

    • 🎬 安装配置说明
    • 🏹 Springboot环境安装
    • 📐 Springboot环境配置
    • 🎯 Springboot环境使用
    • 🏹 Spring环境安装
    • 📐 Spring环境配置
    • 🎯 Spring环境使用
    • 🏹 原生Java环境安装
    • 📐 原生Java环境配置
    • 🎯 原生Java环境使用
    • 🧬 编程式接口
  • 配置项

    • 👜 Springboot环境配置项
    • 👝 Spring环境配置项
    • 🎒 原生Java环境配置项
    • 📚 配置优先级/作用域
  • 声明式接口

    • 🧱 构建接口
    • 🍀 请求方法
    • 🚚 请求地址
    • 🎈 URL 参数
    • 🍭 请求头
    • 👔 请求体
    • 🍮 后端框架
    • 🧁 接口注解
    • 📬 接收数据
    • 🍛 数据转换
    • 🍓 成功/失败条件
    • 🍌 重试机制
    • 🥂 重定向
    • 🍔 Gzip解压
    • 🎂 日志管理
    • ⚽ 回调函数
    • 🍟 异步请求
    • 🛡️ HTTPS
    • 🍪 使用Cookie
    • 🛸 使用代理
    • 🍉 上传下载
      • 🚑 异常处理
    • 编程式接口

      • 请求API

        • 🚀 请求对象
        • 🚢 请求属性
        • ✨ 执行请求
        • 🎊 后端框架
        • 🎪 请求类型
        • 🔮 请求地址
        • 🧀 URL 参数
        • 🚅 请求头
        • 🚋 请求体
        • ⚓ 回调函数
        • 🚁 异步请求
        • 🥯 Cookie
        • 🍜 成功/失败条件
        • 🌶️ 重试机制
        • ⛵ 重定向
        • 🛰️ 请求代理
      • 响应API

        • 🌠 响应对象
        • ✒️ 读取数据
        • 🦋 响应状态码
        • 🏥 响应错误处理
        • 🎧 响应头
        • 🥞 Cookie
    • 模板表达式

      • 🍬 Hello World
      • 🍹 配置属性引用
      • 🍖 变量引用
      • 🥃 动态变量绑定
      • 🥗 参数序号引用
      • 🍍 引用对象属性
      • 🥝 调用对象方法
    • 高级特性

      • 🥪 拦截器
      • 🍏 自定义注解
      • 🍇 组合注解
      • 🥑 自定义转换器
    • v1.5.28文档
    • 声明式接口
    公子骏
    2022-07-01
    目录

    🍉 上传下载

    Forest从 1.4.0 版本开始支持多种形式的文件上传和文件下载功能

    # 上传

    /**
     * 用@DataFile注解修饰要上传的参数对象
     * OnProgress参数为监听上传进度的回调函数
     */
    @Post(url = "/upload")
    Map upload(@DataFile("file") String filePath, OnProgress onProgress);
    
    1
    2
    3
    4
    5
    6

    调用上传接口以及监听上传进度的代码如下:

    Map result = myClient.upload("D:\\TestUpload\\xxx.jpg", progress -> {
        System.out.println("total bytes: " + progress.getTotalBytes());   // 文件大小
        System.out.println("current bytes: " + progress.getCurrentBytes());   // 已上传字节数
        System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%");  // 已上传百分比
        if (progress.isDone()) {   // 是否上传完成
            System.out.println("--------   Upload Completed!   --------");
        }
    });
    
    1
    2
    3
    4
    5
    6
    7
    8

    在文件上传的接口定义中,除了可以使用字符串表示文件路径外,还可以用以下几种类型的对象表示要上传的文件:

    /**
     * File类型对象
     */
    @Post(url = "/upload")
    Map upload(@DataFile("file") File file, OnProgress onProgress);
    
    /**
     * byte数组
     * 使用byte数组和Inputstream对象时一定要定义fileName属性
     */
    @Post(url = "/upload")
    Map upload(@DataFile(value = "file", fileName = "${1}") byte[] bytes, String filename);
    
    /**
     * Inputstream 对象
     * 使用byte数组和Inputstream对象时一定要定义fileName属性
     */
    @Post(url = "/upload")
    Map upload(@DataFile(value = "file", fileName = "${1}") InputStream in, String filename);
    
    /**
     * Spring Web MVC 中的 MultipartFile 对象
     */
    @PostRequest(url = "/upload")
    Map upload(@DataFile(value = "file") MultipartFile multipartFile, OnProgress onProgress);
    
    /**
     * Spring 的 Resource 对象
     */
    @Post(url = "/upload")
    Map upload(@DataFile(value = "file") Resource resource);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

    # 多文件批量上传

    
    /**
     * 上传Map包装的文件列表
     * 其中 ${_key} 代表Map中每一次迭代中的键值
     */
    @PostRequest(url = "/upload")
    ForestRequest<Map> uploadByteArrayMap(@DataFile(value = "file", fileName = "${_key}") Map<String, byte[]> byteArrayMap);
    
    /**
     * 上传List包装的文件列表
     * 其中 ${_index} 代表每次迭代List的循环计数(从零开始计)
     */
    @PostRequest(url = "/upload")
    ForestRequest<Map> uploadByteArrayList(@DataFile(value = "file", fileName = "test-img-${_index}.jpg") List<byte[]> byteArrayList);
    
    /**
     * 上传数组包装的文件列表
     * 其中 ${_index} 代表每次迭代List的循环计数(从零开始计)
     */
    @PostRequest(url = "/upload")
    ForestRequest<Map> uploadByteArrayArray(@DataFile(value = "file", fileName = "test-img-${_index}.jpg") byte[][] byteArrayArray);
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    # 二进制上传

    对于 application/octect-stream 等非form-data的Content-Type类型,直接用@Body修饰要上传的数据参数

    /**
     * 上传Byte数组类型数据
     */
    @Post(
            url = "/upload/${filename}",
            contentType = "application/octet-stream"
    )
    String uploadByteArryr(@Body byte[] body, @Var("filename") String filename);
    
    /**
     * 上传File类型数据
     */
    @Post(
        url = "/upload/${filename}",
        contentType = "application/octet-stream"
    )
    String uploadFile(@Body File file, @Var("filename") String filename);
    
    /**
     * 上传输入流类型数据
     */
    @Post(
        url = "/upload/${filename}",
        contentType = "application/octet-stream"
    )
    String uploadInputStream(@Body InputStream inputStream, @Var("filename") String filename);
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    # 下载

    /**
     * 在方法上加上@DownloadFile注解
     * dir属性表示文件下载到哪个目录
     * filename属性表示文件下载成功后以什么名字保存,如果不填,这默认从URL中取得文件名
     * OnProgress参数为监听上传进度的回调函数
     */
    @Get(url = "http://localhost:8080/images/xxx.jpg")
    @DownloadFile(dir = "${0}", filename = "${1}")
    File downloadFile(String dir, String filename, OnProgress onProgress);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    调用下载接口以及监听上传进度的代码如下:

    File file = myClient.downloadFile("D:\\TestDownload", progress -> {
        System.out.println("total bytes: " + progress.getTotalBytes());   // 文件大小
        System.out.println("current bytes: " + progress.getCurrentBytes());   // 已下载字节数
        System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%");  // 已下载百分比
        if (progress.isDone()) {   // 是否下载完成
            System.out.println("--------   Download Completed!   --------");
        }
    });
    
    1
    2
    3
    4
    5
    6
    7
    8

    如果您不想将文件下载到硬盘上,而是直接在内存中读取,可以去掉@DownloadFile注解,并且用以下几种方式定义接口:

    
    /**
     * 返回类型用byte[],可将下载的文件转换成字节数组
     */
    @GetRequest(url = "http://localhost:8080/images/test-img.jpg")
    byte[] downloadImageToByteArray();
    
    /**
     * 返回类型用InputStream,用流的方式读取文件内容
     */
    @GetRequest(url = "http://localhost:8080/images/test-img.jpg")
    InputStream downloadImageToInputStream();
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    以InputStream类型接受的数据在读取后一定别忘了关闭流

    // 使用 try-with-resource 机制自动关闭流
    try (InputStream in = downloadImageToInputStream()) {
        String content = IOUtils.toString(object, StandardCharsets.UTF_8);
        ... ...
    } catch(Exception ex) {
        ex.printStackTrace();
    }
    
    // 或者自行关闭流        
    InputStream in = null;
    try {
        in = downloadImageToInputStream();
        String content = IOUtils.toString(object, StandardCharsets.UTF_8);
        ... ...
    } catch(Exception ex) {
        ex.printStackTrace();
    } finally {
        if (in != null){
            in.close();
        }
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    注意

    用File类型定义的文件下载接口方法,一定要加上@DownloadFile注解

    帮助我们改善此文档 (opens new window)
    上次更新: 2023/03/07, 12:59:48
    🛸 使用代理
    🚑 异常处理

    ← 🛸 使用代理 🚑 异常处理→

    Theme by Vdoing | Copyright © 2016-2023 公子骏 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式