From 11d9bc7d3789910251ea992c17d4eb747cea240d Mon Sep 17 00:00:00 2001 From: Vinjor Date: Sun, 4 Aug 2024 11:44:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=81=E4=B8=9A=E8=B5=84=E8=B4=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/CompanyController.java | 8 ++- .../admin/CompanyQualsController.java | 46 +++++++++++++++ .../yudao/module/company/entity/Company.java | 1 + .../module/company/entity/CompanyQuals.java | 48 ++++++++++++++++ .../company/mapper/CompanyQualsMapper.java | 20 +++++++ .../company/service/CompanyQualsService.java | 43 ++++++++++++++ .../service/impl/CompanyQualsServiceImpl.java | 57 +++++++++++++++++++ .../module/company/vo/CompanyQualsReqVO.java | 20 +++++++ .../module/company/vo/CompanyQualsRespVO.java | 16 ++++++ .../mapper/company/CompanyQualsMapper.xml | 5 ++ .../core/handler/CellTextWrapHandler.java | 37 ++++++++++++ .../core/handler/SetColumnWidthHandler.java | 35 ++++++++++++ .../framework/excel/core/util/ExcelUtils.java | 30 ++++++++++ 13 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/module/company/controller/admin/CompanyQualsController.java create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/module/company/entity/CompanyQuals.java create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/module/company/mapper/CompanyQualsMapper.java create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/module/company/service/CompanyQualsService.java create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/module/company/service/impl/CompanyQualsServiceImpl.java create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/module/company/vo/CompanyQualsReqVO.java create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/module/company/vo/CompanyQualsRespVO.java create mode 100644 dl-module-base/src/main/resources/mapper/company/CompanyQualsMapper.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/CellTextWrapHandler.java create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SetColumnWidthHandler.java diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/controller/admin/CompanyController.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/controller/admin/CompanyController.java index 2c943f89..f8f29c07 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/controller/admin/CompanyController.java +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/controller/admin/CompanyController.java @@ -28,7 +28,9 @@ import cn.iocoder.yudao.module.company.service.CompanyService; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 企业信息表(每个租户的下属企业信息);(dl_company)表控制层 @@ -139,6 +141,10 @@ public class CompanyController { HttpServletResponse response) throws IOException { List list = companyService.list(); // 导出 Excel - ExcelUtils.write(response, "企业信息表.xls", "数据", Company.class, list); + Map columnWidthMap = new HashMap<>(); + // 第一列的索引是0,宽度设置为20个字符宽 + columnWidthMap.put(9, 20); + columnWidthMap.put(10, 20); + ExcelUtils.write(response, "企业信息表.xls", "数据", Company.class, list,columnWidthMap); } } \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/controller/admin/CompanyQualsController.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/controller/admin/CompanyQualsController.java new file mode 100644 index 00000000..e8e4b654 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/controller/admin/CompanyQualsController.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.company.controller.admin; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.company.entity.CompanyQuals; +import cn.iocoder.yudao.module.company.service.CompanyQualsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * 企业资质信息表(每个租户的下属企业信息);(dl_company_quals)表控制层 + * + * @author : http://www.chiner.pro + * @date : 2024-7-31 + */ +@RestController +@RequestMapping("/base/company-quals") +@Tag(name = "管理后台 - BASE 企业资质管理") +@Validated +public class CompanyQualsController { + @Autowired + private CompanyQualsService companyQualsService; + + /** + * 分页查询 + * @author vinjor-M + * @date 9:52 2024/8/2 + * @param corpId 企业id + **/ + @GetMapping("/page") + @Operation(summary = "获得企业资质信息表分页") + @PreAuthorize("@ss.hasPermission('base:company-quals:query')") + public CommonResult> getCompanyPage(String corpId) { + return success(companyQualsService.list(new LambdaQueryWrapperX().eq(CompanyQuals::getCorpId,corpId))); + } +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/entity/Company.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/entity/Company.java index 33e6f43d..b15bfc76 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/entity/Company.java +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/entity/Company.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.converter.DateFormatConverter; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/entity/CompanyQuals.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/entity/CompanyQuals.java new file mode 100644 index 00000000..d3a999ad --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/entity/CompanyQuals.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.company.entity; + +import cn.iocoder.yudao.converter.DateFormatConverter; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** +* 企业资质信息表 +* @author : http://www.chiner.pro +* @date : 2024-7-31 +*/ +@TableName("base_company_quals") +@Data +@EqualsAndHashCode(callSuper = true) +@ExcelIgnoreUnannotated +public class CompanyQuals extends TenantBaseDO { + /** 主键标识 */ + @TableId(type = IdType.ASSIGN_ID) + private String id ; + /** 资质证书编号 */ + private String qualsNo ; + /** 企业id */ + private String corpId ; + /** 资质证书类型(数据字典quals_type) */ + private String qualsType ; + /** 资质证书名称 */ + private String qualsName ; + /** 附件地址 */ + private String fileUrl ; + /** 有效期开始日期 */ + @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8") + @DateTimeFormat(pattern="yyyy-MM-dd") + private Date startDate ; + /** 有效期截止日期 */ + @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8") + @DateTimeFormat(pattern="yyyy-MM-dd") + private Date endDate ; +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/mapper/CompanyQualsMapper.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/mapper/CompanyQualsMapper.java new file mode 100644 index 00000000..72f64223 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/mapper/CompanyQualsMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.company.mapper; + +import cn.iocoder.yudao.module.company.entity.Company; +import cn.iocoder.yudao.module.company.entity.CompanyQuals; +import cn.iocoder.yudao.module.company.vo.CompanyQualsReqVO; +import cn.iocoder.yudao.module.company.vo.CompanyReqVO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 企业资质信息表 + * @author : http://www.chiner.pro + * @date : 2024-7-31 + */ +@Mapper +public interface CompanyQualsMapper extends BaseMapper{ +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/service/CompanyQualsService.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/service/CompanyQualsService.java new file mode 100644 index 00000000..8efe4efc --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/service/CompanyQualsService.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.company.service; + +import cn.iocoder.yudao.module.company.entity.Company; +import cn.iocoder.yudao.module.company.entity.CompanyQuals; +import cn.iocoder.yudao.module.company.vo.CompanyQualsReqVO; +import cn.iocoder.yudao.module.company.vo.CompanyQualsRespVO; +import cn.iocoder.yudao.module.company.vo.CompanyReqVO; +import cn.iocoder.yudao.module.company.vo.CompanyRespVO; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * 企业资质信息表 + * @author : http://www.chiner.pro + * @date : 2024-7-31 + */ +public interface CompanyQualsService extends IService { + + /** + * 新增企业资质信息 + * @author vinjor-M + * @date 9:56 2024/8/2 + * @param companyQualsRespVO 企业资质对象 + **/ + void saveDataObj(CompanyQualsRespVO companyQualsRespVO); + + /** + * 更新企业资质信息 + * @author vinjor-M + * @date 9:56 2024/8/2 + * @param companyQualsRespVO 企业资质对象 + **/ + void updateDataObj(CompanyQualsRespVO companyQualsRespVO); + + /** + * 删除企业资质 + * @author vinjor-M + * @date 16:33 2024/8/3 + * @param id 企业资质id + **/ + void removeDataObj(String id); +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/service/impl/CompanyQualsServiceImpl.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/service/impl/CompanyQualsServiceImpl.java new file mode 100644 index 00000000..354c2bb9 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/service/impl/CompanyQualsServiceImpl.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.company.service.impl; + +import cn.iocoder.yudao.module.company.entity.Company; +import cn.iocoder.yudao.module.company.entity.CompanyQuals; +import cn.iocoder.yudao.module.company.mapper.CompanyMapper; +import cn.iocoder.yudao.module.company.mapper.CompanyQualsMapper; +import cn.iocoder.yudao.module.company.service.CompanyQualsService; +import cn.iocoder.yudao.module.company.vo.CompanyQualsReqVO; +import cn.iocoder.yudao.module.company.vo.CompanyQualsRespVO; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +@Service +public class CompanyQualsServiceImpl extends ServiceImpl implements CompanyQualsService { + @Resource + private CompanyQualsMapper companyQualsMapper; + + /** + * 新增企业资质信息 + * + * @param companyQualsRespVO 企业资质对象 + * @author vinjor-M + * @date 9:56 2024/8/2 + **/ + @Override + public void saveDataObj(CompanyQualsRespVO companyQualsRespVO) { + + } + + /** + * 更新企业资质信息 + * + * @param companyQualsRespVO 企业资质对象 + * @author vinjor-M + * @date 9:56 2024/8/2 + **/ + @Override + public void updateDataObj(CompanyQualsRespVO companyQualsRespVO) { + + } + + /** + * 删除企业资质 + * + * @param id 企业资质id + * @author vinjor-M + * @date 16:33 2024/8/3 + **/ + @Override + public void removeDataObj(String id) { + + } +} diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/vo/CompanyQualsReqVO.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/vo/CompanyQualsReqVO.java new file mode 100644 index 00000000..9f5bd5a1 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/vo/CompanyQualsReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.company.vo; + +import cn.iocoder.yudao.module.company.entity.Company; +import cn.iocoder.yudao.module.company.entity.CompanyQuals; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 企业资质信息表查询条件实体 + * @author vinjor-M + * @date 17:37 2024/7/31 +**/ +@Data +public class CompanyQualsReqVO extends CompanyQuals { +} diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/vo/CompanyQualsRespVO.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/vo/CompanyQualsRespVO.java new file mode 100644 index 00000000..59f6ded2 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/company/vo/CompanyQualsRespVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.company.vo; + +import cn.iocoder.yudao.module.company.entity.Company; +import cn.iocoder.yudao.module.company.entity.CompanyQuals; +import lombok.Data; + +import java.util.List; + +/** + * 企业资质返回结果或提交vo + * @author vinjor-M + * @date 17:37 2024/7/31 +**/ +@Data +public class CompanyQualsRespVO extends CompanyQuals { +} diff --git a/dl-module-base/src/main/resources/mapper/company/CompanyQualsMapper.xml b/dl-module-base/src/main/resources/mapper/company/CompanyQualsMapper.xml new file mode 100644 index 00000000..11260304 --- /dev/null +++ b/dl-module-base/src/main/resources/mapper/company/CompanyQualsMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/CellTextWrapHandler.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/CellTextWrapHandler.java new file mode 100644 index 00000000..04229115 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/CellTextWrapHandler.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.excel.core.handler; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Row; + +import java.util.List; + +/** + * 自定义列样式 + * @author vinjor-M + * @date 9:48 2024/8/4 +**/ +@Slf4j +public class CellTextWrapHandler implements CellWriteHandler { + @Override + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { + // 在这里可以设置是否为头部,根据需要决定是否要为头部单元格设置样式 + if (!isHead) { + Cell cell = row.createCell(columnIndex); + CellStyle style = writeSheetHolder.getSheet().getWorkbook().createCellStyle(); + style.setWrapText(true); // 设置自动换行 + cell.setCellStyle(style); + } + } + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + // 可以在这里设置合并单元格等操作 + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SetColumnWidthHandler.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SetColumnWidthHandler.java new file mode 100644 index 00000000..0d498ad0 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SetColumnWidthHandler.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.excel.core.handler; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.handler.WriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Sheet; + +import java.util.Map; + +/** + * 自定义列宽度 + * @author vinjor-M + * @date 9:26 2024/8/4 +**/ +@Slf4j +public class SetColumnWidthHandler implements SheetWriteHandler { + private Map columnWidthMap; + + public SetColumnWidthHandler(Map columnWidthMap) { + this.columnWidthMap = columnWidthMap; + } + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + for (Map.Entry entry : columnWidthMap.entrySet()) { + // Excel中宽度的单位是1/256个字符宽度 + writeSheetHolder.getSheet().setColumnWidth(entry.getKey(), entry.getValue() * 256); + } + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index 0bc59947..40ae76d0 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.framework.excel.core.util; +import cn.iocoder.yudao.framework.excel.core.handler.CellTextWrapHandler; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; +import cn.iocoder.yudao.framework.excel.core.handler.SetColumnWidthHandler; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.converters.longconverter.LongStringConverter; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; @@ -11,6 +13,7 @@ import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Map; /** * Excel 工具类 @@ -44,6 +47,33 @@ public class ExcelUtils { response.setContentType("application/vnd.ms-excel;charset=UTF-8"); } + /** + * 将列表以 Excel 响应给前端 + * + * @param response 响应 + * @param filename 文件名 + * @param sheetName Excel sheet 名 + * @param head Excel head 头 + * @param data 数据列表哦 + * @param 泛型,保证 head 和 data 类型的一致性 + * @throws IOException 写入失败的情况 + */ + public static void write(HttpServletResponse response, String filename, String sheetName, + Class head, List data, Map columnWidthMap) throws IOException { + // 输出 Excel + EasyExcel.write(response.getOutputStream(), head) + .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 +// .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 + .registerWriteHandler(new SetColumnWidthHandler(columnWidthMap)) // 自定义列宽 + .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框 + .registerWriteHandler(new CellTextWrapHandler()) // 注册单元格文字换行处理器 + .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 + .sheet(sheetName).doWrite(data); + // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name())); + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + } + public static List read(MultipartFile file, Class head) throws IOException { return EasyExcel.read(file.getInputStream(), head, null) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理