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

Spring下载文件

1、controller

/**
 * 下载文件通过ID
 *
 * @param auditInformationDTO 靓号稽核文件DTO
 * @param servletResponse 响应体
 */
@GetMapping(value = "/downloadAuditFileByAuditFileId")
public void downloadAuditFileByAuditFileId(@ModelAttribute final GoodNumberAuditInformationDTO auditInformationDTO,
                                           final HttpServletResponse servletResponse) throws IOException {
    final GoodNumberAuditInformation auditInformation = goodNumberAuditManagerService.getAuditInformation(auditInformationDTO);

    if (Objects.isNull(auditInformation)){
        throw new DataNotFoundException("文件数据不存在!");
    }

    final String attachmentSize = auditInformation.getAttachmentSize();
    final String attachmentName = auditInformation.getAttachmentName();
    final String attachmentAddress = auditInformation.getAttachmentAddress();

    ResponseHeadUtils.setDownloadFileHead(attachmentName, NumberUtils.toInt(attachmentSize), servletResponse);

    try (final InputStream inputStream = fileOperationStrategy.getObjectInputStream(auditAttachmentBucketName, attachmentAddress)) {
        IOUtils.copy(inputStream, servletResponse.getOutputStream());
    } catch (final IOException ioException) {
        final String fileId = auditInformation.getAuditId();
        log.error("文件下载异常,出现IO异常,下载文件ID是:{}!", fileId, ioException);
        throw ioException;
    }
}

2、ResponseHeadUtils工具类

import com.mocha.order.constant.ContentTypeConstant;
import com.mocha.order.constant.RequestHeadConstant;
import com.mocha.order.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.util.UriUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * http响应头工具类
 * 用于设置不通的头部参数
 *
 * @author yyy
 */
@Slf4j
public class ResponseHeadUtils {

    private ResponseHeadUtils() {}

    /**
     * 最小文件大小
     */
    private static final int MIN_FILE_SIZE = 0;


    /**
     * 设置响应头的ContentDisposition
     *
     * @param fileName 文件名称
     * @param httpServletResponse http响应头
     * @throws IllegalArgumentException 如果文件名称为空
     */
    public static void setContentDisposition(final String fileName, final HttpServletResponse httpServletResponse) {
        if (StringUtils.isBlank(fileName)) {
            log.error("设置响应头ContentDisposition异常:文件名称为空!");
            throw new IllegalArgumentException("文件名称为空!");
        }

        try {
            final String encodedFileName = UriUtils.encode(fileName, StandardCharsets.UTF_8.toString());

            httpServletResponse.setHeader(RequestHeadConstant.CONTENT_DISPOSITION,
                                          "attachment; filename=" + encodedFileName + ";filename*=UTF-8''" + encodedFileName);
        } catch (final UnsupportedEncodingException e) {
            log.error("设置响应头异常:不支持的编码异常!", e);
            throw new CustomException("不支持的编码异常!");
        }
    }

    /**
     * 设置下载文件响应头
     * <p>设置<code>reset()</code>是为了:</p>
     * <ul>
     *     <li>确保在设置新的响应头之前,清除任何可能存在的旧的状态或已设置的响应头,以避免因累积设置而产生错误</li>
     *     <li>避免在执行下载接口之前,拦截器、过滤器等对响应头有个性化的设置,可能导致下载的时候因为响应头设置错误下载异常</li>
     * </ul>
     *
     * @param fileName 文件名称
     * @param fileSize 文件大小
     * @param httpServletResponse http响应头
     * @throws IllegalArgumentException 如果文件大小小于等于{@link #MIN_FILE_SIZE}
     */
    public static void setDownloadFileHead(final String fileName, final int fileSize, final HttpServletResponse httpServletResponse) {
        if (fileSize <= MIN_FILE_SIZE) {
            log.error("设置响应头ContentLength异常:文件大小为空!");
            throw new IllegalArgumentException("文件大小为空!");
        }

        httpServletResponse.reset();
        setContentDisposition(fileName, httpServletResponse);
        httpServletResponse.setContentLength(fileSize);
        httpServletResponse.setContentType(ContentTypeConstant.APPLICATION_OCTET_STREAM);
    }
}

3、前端

/downloadFileById?id=' + id

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

相关文章:

  • 山泽光纤HDMI线:铜线的隐藏力量
  • Unity3D学习FPS游戏(12)敌人检测和攻击玩家
  • 【QT】QSS
  • 并发基础:(淘宝笔试题)三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串【举一反三】
  • MYSQL 库,表 基本操作
  • Gsensor加速度传感器数据异常及概率性卡死
  • 《征服数据结构》滚动数组
  • uni-app生命周期(三)
  • 基于vue框架的城市网约车管理系统v34td(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
  • 民间故事推广系统小程序的设计
  • PMP--一模--解题--41-50
  • 初级练习[3]:Hive SQL子查询应用
  • 其它查询优化策略
  • 基于SSM的大学新生报到系统+LW参考示例
  • Vue3实现打印功能
  • 数据结构---非线性--树
  • prometheus 集成 grafana 保姆级别安装部署
  • 数据结构与算法 第12天(排序)
  • 字符分类函数和字符串函数
  • 【PostgreSQL数据库表膨胀的一些原因】
  • springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
  • 2024121读书笔记|《不急:我们慢慢慢慢来》——做人呢,最重要的是开心
  • 从底层原理上理解ClickHouse 中的 Distributed 引擎
  • tomcat项目报错org.apache.jasper.JasperException: java.lang.NullPointerException
  • Python中的“异常”之旅:探索异常处理的艺术
  • 大语言模型之ICL(上下文学习) - In-Context Learning Creates Task Vectors