package org.jeecg.modules.demo.copywriting.controller;
|
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.util.*;
|
import java.util.regex.Pattern;
|
import java.util.stream.Collectors;
|
import java.io.IOException;
|
import java.io.UnsupportedEncodingException;
|
import java.net.URLDecoder;
|
|
import com.alibaba.fastjson2.JSONObject;
|
import opennlp.tools.dictionary.serializer.Entry;
|
import org.jeecg.modules.demo.copywritingScheme.entity.CopywritingScheme;
|
import org.jeecg.modules.demo.copywritingScheme.service.ICopywritingSchemeService;
|
import org.jeecg.modules.system.entity.SysUser;
|
import org.jeecg.modules.system.service.ISysUserService;
|
import org.jetbrains.annotations.NotNull;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.http.*;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletResponse;
|
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.system.query.QueryGenerator;
|
import org.jeecg.common.system.query.QueryRuleEnum;
|
import org.jeecg.common.util.oConvertUtils;
|
import org.jeecg.modules.demo.contract.entity.SemanticWord;
|
import org.jeecg.modules.demo.contract.service.ISemanticWordService;
|
import org.jeecg.modules.demo.copywriting.entity.Copywriting;
|
import org.jeecg.modules.demo.copywriting.service.ICopywritingService;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
import org.jeecgframework.poi.excel.entity.ExportParams;
|
import org.jeecgframework.poi.excel.entity.ImportParams;
|
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
import org.jeecg.common.system.base.controller.JeecgController;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.http.HttpStatus;
|
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
import org.springframework.web.servlet.ModelAndView;
|
import com.alibaba.fastjson.JSON;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.Operation;
|
import org.jeecg.common.aspect.annotation.AutoLog;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
/**
|
* @Description: 文案
|
* @Author: jeecg-boot
|
* @Date: 2025-10-13
|
* @Version: V1.0
|
*/
|
@Tag(name="文案")
|
@RestController
|
@RequestMapping("/copywriting/copywriting")
|
@Slf4j
|
@EnableAsync
|
public class CopywritingController extends JeecgController<Copywriting, ICopywritingService> {
|
@Autowired
|
public ICopywritingService copywritingService;
|
@Autowired
|
private ISemanticWordService semanticWordService;;
|
@Autowired
|
private ISysUserService sysUserService;
|
|
@Autowired
|
private ICopywritingSchemeService copywritingSchemeService;
|
/**
|
* 分页列表查询
|
*
|
* @param copywriting
|
* @param pageNo
|
* @param pageSize
|
* @param req
|
* @return
|
*/
|
//@AutoLog(value = "文案-分页列表查询")
|
@Operation(summary="文案-分页列表查询")
|
@GetMapping(value = "/list")
|
public Result<IPage<Copywriting>> queryPageList(Copywriting copywriting,
|
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
HttpServletRequest req) {
|
|
QueryWrapper<Copywriting> queryWrapper = QueryGenerator.initQueryWrapper(copywriting, req.getParameterMap());
|
|
if (StringUtils.isNotBlank(copywriting.getTitleLike())) {
|
queryWrapper.like("title", copywriting.getTitleLike());
|
}
|
if (StringUtils.isNotBlank(copywriting.getTitleLike()) && StringUtils.isNotBlank(copywriting.getWordLike())) {
|
queryWrapper.or();
|
}
|
if (StringUtils.isNotBlank(copywriting.getWordLike())){
|
queryWrapper.exists("SELECT 1 FROM semantic_word WHERE semantic_word.id = copywriting.word_id " +
|
"AND semantic_word.word LIKE '%" + copywriting.getWordLike() + "%'");
|
|
}
|
if (StringUtils.isNotBlank(copywriting.getContractId())) {
|
// 1. 拼接关联 contact 表的 EXISTS 子查询,使用 contact.id 作为外键关联
|
// 2. 使用 MyBatis-Plus 的参数占位符避免 SQL 注入,而不是直接字符串拼接
|
String existsSql = "SELECT 1 FROM semantic_word " +
|
"LEFT JOIN contract ON semantic_word.contract_id = contract.id " + // 关联 contact 表(外键关联)
|
"WHERE semantic_word.id = copywriting.word_id " +
|
"AND contract.id = " + copywriting.getContractId(); // 使用 contact 表的 id 作为条件
|
|
// 给 QueryWrapper 设置参数,避免 SQL 注入
|
queryWrapper.exists(existsSql);
|
}
|
Page<Copywriting> page = new Page<Copywriting>(pageNo, pageSize);
|
IPage<Copywriting> pageList = copywritingService.page(page, queryWrapper);
|
for (Copywriting item : pageList.getRecords()) {
|
item.setSemanticWord(semanticWordService.getById(item.getWordId()));
|
}
|
return Result.OK(pageList);
|
}
|
|
|
@Operation(summary="文案-查询发送门户文章总量")
|
@GetMapping(value = "/count")
|
public Result<IPage<Copywriting>> count(Copywriting copywriting,
|
@RequestParam(name="role", defaultValue="无") String role,
|
@RequestParam(name="user", defaultValue="无") String user,
|
HttpServletRequest req) {
|
|
QueryWrapper<Copywriting> queryWrapper = QueryGenerator.initQueryWrapper(copywriting, req.getParameterMap());
|
|
if (StringUtils.isNotBlank(copywriting.getTitleLike())) {
|
queryWrapper.like("title", copywriting.getTitleLike());
|
}
|
if (StringUtils.isNotBlank(copywriting.getTitleLike()) && StringUtils.isNotBlank(copywriting.getWordLike())) {
|
queryWrapper.or();
|
}
|
if (StringUtils.isNotBlank(copywriting.getWordLike())){
|
queryWrapper.exists("SELECT 1 FROM semantic_word WHERE semantic_word.id = copywriting.word_id " +
|
"AND semantic_word.word LIKE '%" + copywriting.getWordLike() + "%'");
|
|
}
|
|
if (!user.equals("无")){
|
QueryWrapper qw = new QueryWrapper<SysUser>();
|
qw.eq("id", user);
|
String userName = ((SysUser)((Page) sysUserService.queryPageList(req, qw, 1, 1).getResult()).getRecords().get(0)).getUsername();
|
queryWrapper.eq("create_by", userName);
|
}
|
long count = copywritingService.count(queryWrapper);
|
return Result.OK(count+"");
|
}
|
|
|
|
@Operation(summary="文案-查询发送门户文章总量")
|
@GetMapping(value = "/upAvgTime")
|
public Result<IPage<Copywriting>> upAvgTime(Copywriting copywriting,
|
HttpServletRequest req) {
|
return Result.OK("5");
|
}
|
|
/**
|
* 添加
|
*
|
* @param copywriting
|
* @return
|
*/
|
@AutoLog(value = "文案-添加")
|
@Operation(summary="文案-添加")
|
@RequiresPermissions("copywriting:copywriting:add")
|
@PostMapping(value = "/add")
|
public Result<String> add(@RequestBody Copywriting copywriting) {
|
if (copywriting.getOutStatus() == null) {
|
copywriting.setOutStatus("1");
|
}
|
copywritingService.save(copywriting);
|
|
return Result.OK("添加成功!");
|
}
|
|
/**
|
* 编辑
|
*
|
* @param copywriting
|
* @return
|
*/
|
@AutoLog(value = "文案-编辑")
|
@Operation(summary="文案-编辑")
|
@RequiresPermissions("copywriting:copywriting:edit")
|
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
|
public Result<String> edit(@RequestBody Copywriting copywriting) {
|
copywritingService.updateById(copywriting);
|
return Result.OK("编辑成功!");
|
}
|
|
/**
|
* 通过id删除
|
*
|
* @param id
|
* @return
|
*/
|
@AutoLog(value = "文案-通过id删除")
|
@Operation(summary="文案-通过id删除")
|
@RequiresPermissions("copywriting:copywriting:delete")
|
@DeleteMapping(value = "/delete")
|
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
|
copywritingService.removeById(id);
|
return Result.OK("删除成功!");
|
}
|
|
/**
|
* 批量删除
|
*
|
* @param ids
|
* @return
|
*/
|
@AutoLog(value = "文案-批量删除")
|
@Operation(summary="文案-批量删除")
|
@RequiresPermissions("copywriting:copywriting:deleteBatch")
|
@DeleteMapping(value = "/deleteBatch")
|
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
this.copywritingService.removeByIds(Arrays.asList(ids.split(",")));
|
return Result.OK("批量删除成功!");
|
}
|
|
/**
|
* 通过id查询
|
*
|
* @param id
|
* @return
|
*/
|
//@AutoLog(value = "文案-通过id查询")
|
@Operation(summary="文案-通过id查询")
|
@GetMapping(value = "/queryById")
|
public Result<Copywriting> queryById(@RequestParam(name="id",required=true) String id) {
|
Copywriting copywriting = copywritingService.getById(id);
|
if(copywriting==null) {
|
return Result.error("未找到对应数据");
|
}
|
return Result.OK(copywriting);
|
}
|
|
/**
|
* 导出excel
|
*
|
* @param request
|
* @param copywriting
|
*/
|
@RequiresPermissions("copywriting:copywriting:exportXls")
|
@RequestMapping(value = "/exportXls")
|
public ModelAndView exportXls(HttpServletRequest request, Copywriting copywriting) {
|
return super.exportXls(request, copywriting, Copywriting.class, "文案");
|
}
|
|
|
@Value("${jeecg.path.upload}")
|
private String uploadPath;
|
/**
|
* 通过excel导入数据
|
*
|
* @param request
|
* @param response
|
* @return
|
*/
|
@RequiresPermissions("copywriting:copywriting:importExcel")
|
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
|
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
|
return super.importExcel(request, response, Copywriting.class);
|
}
|
|
|
@RequiresPermissions("copywriting:copywriting:aiCreateCopyWriting")
|
@RequestMapping(value = "/aiCreateCopyWriting", method = RequestMethod.POST)
|
public Result<?> aiCreateCopyWriting(
|
@RequestParam(name = "file", required = false) String jianli,
|
@RequestParam(name = "url", required = false) String jianli2,
|
@RequestParam String wenanyaoqiu,
|
@RequestParam String louchu,
|
@RequestParam String youshang,
|
@RequestParam String wenti,
|
@RequestParam String user,
|
@RequestParam String csId) {
|
if (csId == null){
|
csId = "2020795745607319553";
|
}
|
CopywritingScheme copywritingScheme = new CopywritingScheme();
|
copywritingScheme.setId(csId);
|
return getResult(jianli, jianli2, wenanyaoqiu, louchu, youshang, wenti, user, copywritingScheme);
|
}
|
|
public Result<?> getResult(String jianli, String jianli2, String wenanyaoqiu, String louchu, String youshang, String wenti, String user, CopywritingScheme cs) {
|
QueryWrapper<CopywritingScheme> copywritingSchemeQueryWrapper = new QueryWrapper<>();
|
|
if (cs.getId() == null){
|
cs.setId("2020795745607319553");
|
}
|
copywritingSchemeQueryWrapper.eq("id", cs.getId());
|
List<CopywritingScheme> list = copywritingSchemeService.list(copywritingSchemeQueryWrapper);
|
if(list.size()==0) {
|
return Result.error("方案不存在");
|
} else {
|
cs = list.get(0);
|
}
|
// 配置信息
|
String serverFileRoot = uploadPath;
|
String workflowUrl = cs.getWorkflowUrl();
|
String fileUploadUrl = cs.getFileUploadUrl(); // 文件上传接口(假设)
|
String authToken = cs.getAuthToken();
|
String userId = user;
|
String appId = cs.getAppId();
|
|
try {
|
Map<String, Object> inputs = new HashMap<>();
|
if (jianli != null) {
|
// 步骤2:构建 inputs 参数(按接口要求格式)
|
List<String> jianliFileList = Arrays.asList(jianli.split(","));
|
if (jianliFileList != null && !jianliFileList.isEmpty()) {
|
// 步骤1:上传简历文件,获取 upload_file_id 列表
|
List<String> jianliFileIds = new ArrayList<>();
|
for (String fileName : jianliFileList) {
|
// 修正:只过滤路径遍历字符,保留合法的 /
|
String safeFileName = File.separator + fileName.trim()
|
// 过滤 ../ 和 ./ 序列(防止访问上级目录)
|
.replaceAll("\\.\\./", "")
|
.replaceAll("\\./", "");
|
|
// 进一步安全校验:确保拼接后的文件路径在服务器根目录下(核心安全措施)
|
File file = new File(serverFileRoot + safeFileName);
|
String canonicalPath = file.getCanonicalPath(); // 获取标准化路径(自动解析 ../ 等)
|
String canonicalRootPath = new File(serverFileRoot).getCanonicalPath();
|
|
// 校验:如果文件路径不在服务器根目录下,视为非法请求
|
if (!canonicalPath.startsWith(canonicalRootPath)) {
|
throw new RuntimeException("非法文件访问:" + fileName);
|
}
|
|
// 再判断文件是否存在
|
if (!file.exists() || !file.isFile()) {
|
return Result.error("服务器不存在文件:" + safeFileName + ",路径:" + file.getAbsolutePath());
|
}
|
// 调用文件上传接口,获取 upload_file_id
|
String fileId = uploadFileToServer(file, fileUploadUrl, authToken);
|
jianliFileIds.add(fileId);
|
}
|
|
|
// 处理简历文件(jianli 是 variable_name,对应接口的 {variable_name})
|
if (!jianliFileIds.isEmpty()) {
|
// 若支持多个文件,可能需要数组形式;单个文件则直接放对象
|
List<Map<String, String>> jianliFiles = new ArrayList<>();
|
for (String fileId : jianliFileIds) {
|
Map<String, String> fileInfo = new HashMap<>();
|
fileInfo.put("transfer_method", "local_file"); // 固定值,接口要求
|
fileInfo.put("upload_file_id", fileId); // 上传文件返回的ID
|
fileInfo.put("type", "document"); // 文件类型,如 document/image 等(按接口要求)
|
jianliFiles.add(fileInfo);
|
}
|
inputs.put("jianli", jianliFiles); // jianli 对应 {variable_name}
|
} else {
|
inputs.put("jianli", new ArrayList<>()); // 空文件列表
|
}
|
}
|
}
|
|
if (jianli2 != null) {
|
inputs.put("jianli2", jianli2);
|
}
|
// 添加其他文本参数
|
inputs.put("benchmarkUrl", wenanyaoqiu);
|
inputs.put("louchu", louchu);
|
inputs.put("youshang", youshang);
|
inputs.put("wenti", wenti);
|
|
// 添加系统参数
|
inputs.put("sys.user_id", userId);
|
inputs.put("sys.app_id", appId);
|
|
// 步骤3:构建完整请求体
|
Map<String, Object> requestBody = new HashMap<>();
|
requestBody.put("inputs", inputs); // 顶层 inputs 容器
|
requestBody.put("user", user); // 顶层 inputs 容器
|
|
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
// 连接超时:建立TCP连接的超时时间,单位毫秒(建议设5秒)
|
factory.setConnectTimeout(5000);
|
// 读取超时:等待服务端响应数据的超时时间,单位毫秒(根据接口耗时调整,这里设30秒)
|
factory.setReadTimeout(200000);
|
// 步骤4:调用工作流接口
|
RestTemplate restTemplate = new RestTemplate(factory);
|
HttpHeaders headers = new HttpHeaders();
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
headers.set("Authorization", "Bearer " + authToken);
|
|
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
|
ResponseEntity<String> response = restTemplate.postForEntity(workflowUrl, requestEntity, String.class);
|
|
if (response.getStatusCode() == HttpStatus.OK) {
|
if (JSONObject.parseObject(response.getBody()).getJSONObject("data").get("outputs") == null) {
|
return Result.error(JSONObject.parseObject(response.getBody()).getJSONObject("data").getString("error"));
|
}
|
else{
|
String test = JSONObject.parseObject(response.getBody()).getJSONObject("data").getJSONObject("outputs").getString("http");
|
|
// ========== 中间操作:MD转HTML格式文本(保留所有回车,新增####四级标题处理) ==========
|
// 1. 定义MD语法正则(补充####四级标题,其他保留)
|
Pattern h1Pattern = Pattern.compile("^# (.*)", Pattern.MULTILINE);
|
Pattern h2Pattern = Pattern.compile("^## (.*)", Pattern.MULTILINE);
|
Pattern h3Pattern = Pattern.compile("^### (.*)", Pattern.MULTILINE);
|
Pattern h4Pattern = Pattern.compile("^#### (.*)", Pattern.MULTILINE); // 新增:四级标题正则
|
Pattern ulStartPattern = Pattern.compile("^- (.*)", Pattern.MULTILINE);
|
Pattern boldPattern = Pattern.compile("\\*\\*(.*?)\\*\\*");
|
Pattern hrPattern = Pattern.compile("^---+$", Pattern.MULTILINE);
|
|
// 2. 逐步替换MD语法为HTML标签(保留所有换行,新增四级标题转换)
|
test = h1Pattern.matcher(test).replaceAll("<h1>$1</h1>"); // 一级标题→<h1>
|
test = h2Pattern.matcher(test).replaceAll("<h2>$1</h2>"); // 二级标题→<h2>
|
test = h3Pattern.matcher(test).replaceAll("<h3>$1</h3>"); // 三级标题→<h3>
|
test = h4Pattern.matcher(test).replaceAll("<h4>$1</h4>"); // 新增:四级标题→<h4>
|
test = boldPattern.matcher(test).replaceAll("<strong>$1</strong>"); // 加粗→<strong>
|
test = hrPattern.matcher(test).replaceAll("<hr/>"); // 分隔线→<hr/>
|
|
// 处理无序列表(先标记列表项,再包裹<ul>)
|
test = ulStartPattern.matcher(test).replaceAll("<li>$1</li>");
|
test = test.replaceAll("(<li>.*?</li>\\r?\\n?)+", "<ul>$0</ul>");
|
|
// 保留原有回车(将\n转为HTML换行<br>,同时保留原始换行符)
|
test = test.replaceAll("\\r?\\n", "<br/>\n");
|
|
// ========== 转换结束,test为HTML格式且处理了####四级标题 ==========
|
|
return Result.OK("文案生成成功", test);
|
}
|
|
} else {
|
return Result.error("工作流接口异常,状态码:" + response.getStatusCodeValue());
|
}
|
|
} catch (NullPointerException e) {
|
e.printStackTrace();
|
return Result.error("不支持的文件格式:" + jianli.split("\\.")[jianli.split("\\.").length - 1]);
|
} catch (Exception e) {
|
e.printStackTrace();
|
return Result.error("生成文案异常:" + e.getMessage());
|
}
|
}
|
|
|
/**
|
* 新增的生成标题接口方法
|
*/
|
@RequiresPermissions("copywriting:copywriting:aiCreateTitle")
|
@RequestMapping(value = "/aiCreateTitle", method = RequestMethod.POST)
|
public Result<?> aiCreateTitle(
|
@RequestParam String louchu,
|
@RequestParam String yuyici,
|
@RequestParam String startTime,
|
@RequestParam String endTime,
|
@RequestParam String user) { // 保留user参数,用于接口鉴权/归属
|
|
return getResult(louchu, yuyici, startTime, endTime, user);
|
}
|
|
public static Result<?> getResult(String louchu, String yuyici, String startTime, String endTime, String user) {
|
// 2. 配置固定参数(和原有方法保持一致,可根据实际情况调整)
|
String workflowUrl = "http://14.103.174.44/v1/workflows/run"; // 标题生成的工作流地址,若和文案不同需修改
|
String authToken = "app-F09iyl3p5448JoKufR2CRpWG";
|
String appId = "cf85fe4d-b76b-4c4c-801a-1336c880d473";
|
|
try {
|
// 3. 构建inputs参数(适配标题生成接口的参数格式)
|
Map<String, Object> inputs = new HashMap<>();
|
// 添加业务参数
|
inputs.put("louchu", louchu); // 露出
|
inputs.put("yuyici", yuyici); // 语气词
|
inputs.put("startTime", startTime); // 开始时间
|
inputs.put("endTime", endTime); // 结束时间
|
|
// 添加系统参数(和原有方法一致)
|
inputs.put("sys.user_id", user);
|
inputs.put("sys.app_id", appId);
|
|
// 4. 构建完整请求体
|
Map<String, Object> requestBody = new HashMap<>();
|
requestBody.put("inputs", inputs); // 顶层inputs容器
|
requestBody.put("user", user); // 顶层user参数(保持和原有接口一致)
|
|
// 5. 调用工作流接口
|
RestTemplate restTemplate = new RestTemplate();
|
HttpHeaders headers = new HttpHeaders();
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
headers.set("Authorization", "Bearer " + authToken);
|
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
|
ResponseEntity<String> response = restTemplate.postForEntity(workflowUrl, requestEntity, String.class);
|
|
// 6. 处理接口返回结果
|
if (response.getStatusCode() == HttpStatus.OK) {
|
JSONObject responseJson = JSONObject.parseObject(response.getBody());
|
JSONObject dataJson = responseJson.getJSONObject("data");
|
|
// 校验返回结果结构
|
if (dataJson == null) {
|
return Result.error("接口返回数据格式异常:无data字段");
|
}
|
if (dataJson.get("outputs") == null) {
|
String errorMsg = dataJson.getString("error") != null ? dataJson.getString("error") : "标题生成失败,无具体错误信息";
|
return Result.error(errorMsg);
|
}
|
|
// 提取标题结果(假设outputs里的key是"title",需根据实际接口返回调整)
|
String title = dataJson.getJSONObject("outputs").getString("title");
|
if (title != null) {
|
return Result.OK("标题生成成功", title);
|
} else {
|
try {
|
return Result.OK(JSONObject.parseObject(dataJson.get("outputs").toString()).get("llm"));
|
} catch (Exception e ){
|
|
}
|
|
}
|
} else {
|
return Result.error("工作流接口调用异常,状态码:" + response.getStatusCodeValue());
|
}
|
|
} catch (Exception e) {
|
e.printStackTrace();
|
return Result.error("生成标题异常:" + e.getMessage());
|
}
|
return Result.error("");
|
}
|
|
/**
|
* 调用文件上传接口,获取 upload_file_id(修正版)
|
*/
|
private String uploadFileToServer(File file, String uploadUrl, String authToken) throws Exception {
|
// 构建文件上传请求(multipart/form-data 格式)
|
HttpHeaders headers = new HttpHeaders();
|
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
headers.set("Authorization", "Bearer " + authToken);
|
|
// 读取文件内容
|
byte[] fileBytes = new byte[(int) file.length()];
|
try (FileInputStream fis = new FileInputStream(file)) {
|
fis.read(fileBytes);
|
}
|
|
// 构建多部分请求体
|
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
|
parts.add("file", new ByteArrayResource(fileBytes) {
|
@Override
|
public String getFilename() {
|
return file.getName(); // 必须设置文件名
|
}
|
});
|
|
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);
|
RestTemplate restTemplate = new RestTemplate();
|
ResponseEntity<Map> response = restTemplate.postForEntity(uploadUrl, requestEntity, Map.class);
|
|
// 修正:只要状态码是200 OK,且包含id字段,就是上传成功
|
if ((response.getStatusCode() == HttpStatus.OK || response.getStatusCode() == HttpStatus.CREATED) && response.getBody() != null) {
|
Object fileId = response.getBody().get("id");
|
if (fileId != null) {
|
return fileId.toString(); // 成功返回upload_file_id
|
} else {
|
throw new RuntimeException("文件上传成功,但未返回id字段,响应:" + response.getBody());
|
}
|
} else {
|
throw new RuntimeException("文件上传失败,状态码:" + response.getStatusCode() + ",响应:" + response.getBody());
|
}
|
}
|
}
|