You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
7.0 KiB

3 months ago
  1. package com.example.demo.Util;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.core.io.FileSystemResource;
  5. import org.springframework.http.*;
  6. import org.springframework.http.client.SimpleClientHttpRequestFactory;
  7. import org.springframework.http.converter.StringHttpMessageConverter;
  8. import org.springframework.util.LinkedMultiValueMap;
  9. import org.springframework.util.MultiValueMap;
  10. import org.springframework.web.client.RestTemplate;
  11. import java.io.File;
  12. import java.io.IOException;
  13. import java.nio.charset.Charset;
  14. import java.util.HashMap;
  15. import java.util.Map;
  16. /**
  17. * Excel文件上传工具类
  18. */
  19. public class ExcelUploadUtil {
  20. private static final Logger logger = LoggerFactory.getLogger(ExcelUploadUtil.class);
  21. // 默认配置
  22. private static final int DEFAULT_CONNECT_TIMEOUT = 30000; // 30秒
  23. private static final int DEFAULT_READ_TIMEOUT = 60000; // 60秒
  24. private final RestTemplate restTemplate;
  25. private final String uploadUrl;
  26. private final Map<String, String> defaultHeaders;
  27. private final Map<String, String> defaultParams;
  28. /**
  29. * 构造方法
  30. *
  31. * @param uploadUrl 上传接口URL
  32. */
  33. public ExcelUploadUtil(String uploadUrl) {
  34. this(uploadUrl, new HashMap<>(), new HashMap<>());
  35. }
  36. /**
  37. * 构造方法
  38. *
  39. * @param uploadUrl 上传接口URL
  40. * @param defaultHeaders 默认请求头
  41. * @param defaultParams 默认请求参数
  42. */
  43. public ExcelUploadUtil(String uploadUrl, Map<String, String> defaultHeaders, Map<String, String> defaultParams) {
  44. this.uploadUrl = uploadUrl;
  45. this.defaultHeaders = new HashMap<>(defaultHeaders);
  46. this.defaultParams = new HashMap<>(defaultParams);
  47. this.restTemplate = createRestTemplate(DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT);
  48. }
  49. /**
  50. * 创建RestTemplate (Spring Boot 1.x 兼容版本)
  51. */
  52. private RestTemplate createRestTemplate(int connectTimeout, int readTimeout) {
  53. RestTemplate restTemplate = new RestTemplate();
  54. // 添加字符串消息转换器 (Spring 1.x 使用Charset而不是StandardCharsets)
  55. restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
  56. // 设置超时 (Spring 1.x 方式)
  57. SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
  58. factory.setConnectTimeout(connectTimeout);
  59. factory.setReadTimeout(readTimeout);
  60. restTemplate.setRequestFactory(factory);
  61. return restTemplate;
  62. }
  63. /**
  64. * 上传Excel文件
  65. *
  66. * @param excelFile Excel文件
  67. * @param targetDir 目标目录
  68. * @return 上传结果
  69. * @throws IOException 文件操作异常
  70. * @throws UploadException 上传异常
  71. */
  72. public String uploadExcel(File excelFile, String targetDir) throws IOException, UploadException {
  73. return uploadExcel(excelFile, targetDir, new HashMap<>(), new HashMap<>());
  74. }
  75. /**
  76. * 上传Excel文件带自定义参数
  77. *
  78. * @param excelFile Excel文件
  79. * @param targetDir 目标目录
  80. * @param customHeaders 自定义请求头
  81. * @param customParams 自定义请求参数
  82. * @return 上传结果
  83. * @throws IOException 文件操作异常
  84. * @throws UploadException 上传异常
  85. */
  86. public String uploadExcel(File excelFile, String targetDir,
  87. Map<String, String> customHeaders,
  88. Map<String, String> customParams) throws IOException, UploadException {
  89. // 验证文件
  90. validateFile(excelFile);
  91. try {
  92. // 准备请求
  93. HttpEntity<MultiValueMap<String, Object>> requestEntity = prepareRequest(excelFile, targetDir, customHeaders, customParams);
  94. // 执行上传
  95. ResponseEntity<String> response = restTemplate.exchange(
  96. uploadUrl,
  97. HttpMethod.POST,
  98. requestEntity,
  99. String.class
  100. );
  101. // 处理响应
  102. return handleResponse(response, excelFile.getName());
  103. } catch (Exception e) {
  104. logger.error("Excel文件上传失败: {}", excelFile.getAbsolutePath(), e);
  105. throw new UploadException("文件上传失败: " + e.getMessage(), e);
  106. }
  107. }
  108. /**
  109. * 验证文件
  110. */
  111. private void validateFile(File file) throws IOException {
  112. if (file == null) {
  113. throw new IOException("文件不能为null");
  114. }
  115. if (!file.exists()) {
  116. throw new IOException("文件不存在: " + file.getAbsolutePath());
  117. }
  118. if (!file.isFile()) {
  119. throw new IOException("不是有效的文件: " + file.getAbsolutePath());
  120. }
  121. if (file.length() == 0) {
  122. throw new IOException("文件内容为空: " + file.getAbsolutePath());
  123. }
  124. if (!file.getName().toLowerCase().endsWith(".xlsx") &&
  125. !file.getName().toLowerCase().endsWith(".xls")) {
  126. throw new IOException("仅支持Excel文件(.xlsx, .xls)");
  127. }
  128. }
  129. /**
  130. * 准备请求
  131. */
  132. private HttpEntity<MultiValueMap<String, Object>> prepareRequest(File file, String targetDir,
  133. Map<String, String> customHeaders,
  134. Map<String, String> customParams) {
  135. // 设置请求头
  136. HttpHeaders headers = new HttpHeaders();
  137. headers.setContentType(MediaType.MULTIPART_FORM_DATA);
  138. // 添加默认和自定义请求头
  139. defaultHeaders.forEach(headers::set);
  140. customHeaders.forEach(headers::set);
  141. // 准备请求体
  142. MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
  143. body.add("file", new FileSystemResource(file));
  144. body.add("dir", targetDir);
  145. // 添加默认和自定义参数
  146. defaultParams.forEach(body::add);
  147. customParams.forEach(body::add);
  148. return new HttpEntity<>(body, headers);
  149. }
  150. /**
  151. * 处理响应
  152. */
  153. private String handleResponse(ResponseEntity<String> response, String filename) throws UploadException {
  154. if (response.getStatusCode() == HttpStatus.OK) {
  155. logger.info("文件上传成功: {}", filename);
  156. return response.getBody();
  157. } else {
  158. String errorMsg = String.format("上传接口返回错误状态码: %d, 响应: %s",
  159. response.getStatusCodeValue(), response.getBody());
  160. logger.error(errorMsg);
  161. throw new UploadException(errorMsg);
  162. }
  163. }
  164. /**
  165. * 自定义上传异常
  166. */
  167. public static class UploadException extends Exception {
  168. public UploadException(String message) {
  169. super(message);
  170. }
  171. public UploadException(String message, Throwable cause) {
  172. super(message, cause);
  173. }
  174. }
  175. }