|
|
@@ -0,0 +1,137 @@
|
|
|
+package shop.alien.store.controller;
|
|
|
+
|
|
|
+import io.swagger.annotations.Api;
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import io.swagger.annotations.ApiParam;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.core.io.ClassPathResource;
|
|
|
+import org.springframework.core.io.Resource;
|
|
|
+import org.springframework.web.bind.annotation.CrossOrigin;
|
|
|
+import org.springframework.web.bind.annotation.GetMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.net.URLEncoder;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 通用模板下载控制器
|
|
|
+ * 支持通过type参数下载不同类型的模板文件
|
|
|
+ *
|
|
|
+ * @author system
|
|
|
+ */
|
|
|
+@Api(tags = {"通用模板下载"})
|
|
|
+@Slf4j
|
|
|
+@RestController
|
|
|
+@CrossOrigin
|
|
|
+@RequestMapping("/template")
|
|
|
+public class TemplateDownloadController {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 模板类型与文件名的映射关系
|
|
|
+ * key: 模板类型
|
|
|
+ * value: 模板文件名(相对于 resources/templates 目录)
|
|
|
+ */
|
|
|
+ private static final Map<String, String> TEMPLATE_MAP = new HashMap<String, String>() {{
|
|
|
+ put("clearing_receipt", "clearing_receipt.xlsx");
|
|
|
+ // 可以根据需要添加更多模板类型映射
|
|
|
+ // put("type2", "template2.xlsx");
|
|
|
+ // put("type3", "template3.xls");
|
|
|
+ }};
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通用模板下载接口
|
|
|
+ *
|
|
|
+ * @param type 模板类型,对应 TEMPLATE_MAP 中的 key
|
|
|
+ * @param response HTTP响应对象
|
|
|
+ */
|
|
|
+ @ApiOperation("下载模板文件")
|
|
|
+ @GetMapping("/download")
|
|
|
+ public void downloadTemplate(
|
|
|
+ @ApiParam(value = "模板类型", required = true, example = "clearing_receipt")
|
|
|
+ @RequestParam("type") String type,
|
|
|
+ HttpServletResponse response) {
|
|
|
+
|
|
|
+ log.info("开始下载模板,type: {}", type);
|
|
|
+
|
|
|
+ // 验证模板类型
|
|
|
+ if (type == null || type.trim().isEmpty()) {
|
|
|
+ log.error("模板类型参数不能为空");
|
|
|
+ throw new RuntimeException("模板类型参数不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String fileName = TEMPLATE_MAP.get(type);
|
|
|
+ if (fileName == null) {
|
|
|
+ log.error("不支持的模板类型: {}", type);
|
|
|
+ throw new RuntimeException("不支持的模板类型: " + type);
|
|
|
+ }
|
|
|
+
|
|
|
+ InputStream inputStream = null;
|
|
|
+ OutputStream outputStream = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 从resources/templates目录读取模板文件
|
|
|
+ Resource resource = new ClassPathResource("templates/" + fileName);
|
|
|
+
|
|
|
+ // 检查文件是否存在
|
|
|
+ if (!resource.exists()) {
|
|
|
+ log.error("模板文件不存在: templates/{}", fileName);
|
|
|
+ throw new RuntimeException("模板文件不存在: " + fileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ inputStream = resource.getInputStream();
|
|
|
+
|
|
|
+ // 根据文件扩展名设置Content-Type
|
|
|
+ String contentType;
|
|
|
+ if (fileName.toLowerCase().endsWith(".xlsx")) {
|
|
|
+ contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
|
+ } else if (fileName.toLowerCase().endsWith(".xls")) {
|
|
|
+ contentType = "application/vnd.ms-excel";
|
|
|
+ } else {
|
|
|
+ contentType = "application/octet-stream";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置响应头
|
|
|
+ response.reset();
|
|
|
+ response.setContentType(contentType);
|
|
|
+ response.setCharacterEncoding("utf-8");
|
|
|
+
|
|
|
+ // 设置文件下载响应头,支持中文文件名
|
|
|
+ String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
|
|
|
+ response.setHeader("Content-Disposition",
|
|
|
+ "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
|
|
|
+
|
|
|
+ // 输出文件流
|
|
|
+ outputStream = response.getOutputStream();
|
|
|
+ byte[] buffer = new byte[1024];
|
|
|
+ int length;
|
|
|
+ while ((length = inputStream.read(buffer)) > 0) {
|
|
|
+ outputStream.write(buffer, 0, length);
|
|
|
+ }
|
|
|
+ outputStream.flush();
|
|
|
+
|
|
|
+ log.info("模板下载成功,type: {}, fileName: {}", type, fileName);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("下载模板失败,type: {}, fileName: {}", type, fileName, e);
|
|
|
+ throw new RuntimeException("下载模板失败:" + e.getMessage());
|
|
|
+ } finally {
|
|
|
+ // 关闭流
|
|
|
+ try {
|
|
|
+ if (inputStream != null) {
|
|
|
+ inputStream.close();
|
|
|
+ }
|
|
|
+ if (outputStream != null) {
|
|
|
+ outputStream.close();
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("关闭流失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|