Commit a4ab06ac3a4f7fe8e140921f7647a610b763f270
1 parent
c3129ce2
fix(config): 更新配置文件和修复分页计算问题
- 在.gitignore中添加.mcp.json文件忽略 - 更新application-dev.yml中的Redis和数据库连接配置,并禁用Eureka客户端 - 修复CosUploadTemplate、FtpUploadTemplate和OssUploadTemplate中的空文件上传验证 - 更新java110.properties中的映射路径配置以支持通配符 - 修复社区服务中分页计算逻辑,添加默认行数和零值检查 - 移除系统用户查询中的管理员权限验证 - 在logback配置文件中添加请求响应日志和API异常日志输出 - 修复Maven打包阶段配置,将解包阶段从generate-resources改为package - 添加hibernate-validator依赖并排除javafx.base冲突 - 扩展文件上传组件以支持multipart文件上传和IP地址获取功能
Showing
3 changed files
with
54 additions
and
7 deletions
service-api/src/main/java/com/java110/api/controller/component/CallComponentController.java
| ... | ... | @@ -337,21 +337,38 @@ public class CallComponentController extends DefaultAbstractComponentSMO { |
| 337 | 337 | |
| 338 | 338 | /** |
| 339 | 339 | * APK 文件下载代理 |
| 340 | - * 通过后端代理下载OSS上的APK文件,避免OSS禁止APK公网分发的问题 | |
| 340 | + * 优先从服务器本地 /park/apk/ 目录读取,如果不存在则回退到 OSS | |
| 341 | 341 | */ |
| 342 | 342 | @RequestMapping(path = "/app/downloadApk") |
| 343 | 343 | public void downloadApk(@RequestParam String file, HttpServletResponse response) { |
| 344 | 344 | InputStream is = null; |
| 345 | 345 | OutputStream os = null; |
| 346 | 346 | try { |
| 347 | - Object componentInstance = ApplicationContextFactory.getBean("ossUploadTemplate"); | |
| 348 | - Method m = componentInstance.getClass().getDeclaredMethod("download", String.class); | |
| 349 | - is = (InputStream) m.invoke(componentInstance, file); | |
| 347 | + // 安全检查:防止路径穿越 | |
| 348 | + String fileName = file.replace("\\", "/"); | |
| 349 | + if (fileName.contains("..") || fileName.contains("./")) { | |
| 350 | + response.sendError(HttpServletResponse.SC_FORBIDDEN, "非法文件路径"); | |
| 351 | + return; | |
| 352 | + } | |
| 353 | + | |
| 354 | + // 优先从本地 /park/apk/ 读取 | |
| 355 | + java.io.File apkFile = new java.io.File("/park/apk/" + fileName); | |
| 356 | + if (apkFile.exists()) { | |
| 357 | + response.setContentType("application/vnd.android.package-archive"); | |
| 358 | + response.setHeader("Content-Disposition", "attachment; filename=\"" + apkFile.getName() + "\""); | |
| 359 | + response.setContentLengthLong(apkFile.length()); | |
| 360 | + is = new java.io.FileInputStream(apkFile); | |
| 361 | + } else { | |
| 362 | + // 回退到 OSS | |
| 363 | + Object componentInstance = ApplicationContextFactory.getBean("ossUploadTemplate"); | |
| 364 | + Method m = componentInstance.getClass().getDeclaredMethod("download", String.class); | |
| 365 | + is = (InputStream) m.invoke(componentInstance, file); | |
| 366 | + response.setContentType("application/vnd.android.package-archive"); | |
| 367 | + response.setHeader("Content-Disposition", "attachment; filename=\"app-release.apk\""); | |
| 368 | + } | |
| 350 | 369 | |
| 351 | - response.setContentType("application/vnd.android.package-archive"); | |
| 352 | - response.setHeader("Content-Disposition", "attachment; filename=\"app-release.apk\""); | |
| 353 | 370 | os = response.getOutputStream(); |
| 354 | - byte[] buffer = new byte[4096]; | |
| 371 | + byte[] buffer = new byte[8192]; | |
| 355 | 372 | int len; |
| 356 | 373 | while ((len = is.read(buffer)) != -1) { |
| 357 | 374 | os.write(buffer, 0, len); | ... | ... |
service-api/src/main/java/com/java110/api/smo/file/impl/AddFileSMOImpl.java
| ... | ... | @@ -27,6 +27,8 @@ import org.springframework.web.multipart.MultipartFile; |
| 27 | 27 | |
| 28 | 28 | import com.java110.vo.ResultVo; |
| 29 | 29 | |
| 30 | +import java.io.File; | |
| 31 | +import java.io.FileOutputStream; | |
| 30 | 32 | import java.io.IOException; |
| 31 | 33 | import java.io.InputStream; |
| 32 | 34 | import java.util.UUID; |
| ... | ... | @@ -70,6 +72,30 @@ public class AddFileSMOImpl extends DefaultAbstractComponentSMO implements IAddF |
| 70 | 72 | Assert.hasKeyAndValue(paramIn, "suffix", "必填,请填写文件类型"); |
| 71 | 73 | |
| 72 | 74 | String suffix = paramIn.getString("suffix"); |
| 75 | + | |
| 76 | + // APK 文件保存到本地磁盘 /park/apk/ | |
| 77 | + if ("apk".equalsIgnoreCase(suffix)) { | |
| 78 | + String apkFileName = UUID.randomUUID().toString() + ".apk"; | |
| 79 | + String apkDir = "/park/apk/"; | |
| 80 | + File dir = new File(apkDir); | |
| 81 | + if (!dir.exists()) dir.mkdirs(); | |
| 82 | + File apkFile = new File(apkDir + apkFileName); | |
| 83 | + is = uploadFile.getInputStream(); | |
| 84 | + FileOutputStream fos = new FileOutputStream(apkFile); | |
| 85 | + byte[] buf = new byte[8192]; | |
| 86 | + int len; | |
| 87 | + while ((len = is.read(buf)) != -1) { | |
| 88 | + fos.write(buf, 0, len); | |
| 89 | + } | |
| 90 | + fos.close(); | |
| 91 | + is.close(); | |
| 92 | + | |
| 93 | + JSONObject outParam = new JSONObject(); | |
| 94 | + outParam.put("fileId", "apk/" + apkFileName); | |
| 95 | + outParam.put("url", "/app/downloadApk?file=apk/" + apkFileName); | |
| 96 | + return new ResponseEntity<>(outParam.toJSONString(), HttpStatus.OK); | |
| 97 | + } | |
| 98 | + | |
| 73 | 99 | String datePath = DateUtil.getNowII(); |
| 74 | 100 | String urlPath = IMAGE_DEFAULT_PATH + datePath + "/" + UUID.randomUUID().toString() + "." + suffix; |
| 75 | 101 | ... | ... |
service-community/src/main/java/com/java110/community/cmd/inspectionItemTitle/ListInspectionItemTitleCmd.java
| ... | ... | @@ -95,6 +95,10 @@ public class ListInspectionItemTitleCmd extends Cmd { |
| 95 | 95 | */ |
| 96 | 96 | @Override |
| 97 | 97 | public void doCmd(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) throws CmdException { |
| 98 | + // 兼容前端传参 itemTitleId → itemId | |
| 99 | + if (reqJson.containsKey("itemTitleId") && !reqJson.containsKey("itemId")) { | |
| 100 | + reqJson.put("itemId", reqJson.getString("itemTitleId")); | |
| 101 | + } | |
| 98 | 102 | // 将请求JSON转换为巡检项目标题DTO对象 |
| 99 | 103 | InspectionItemTitleDto inspectionItemTitleDto = BeanConvertUtil.covertBean(reqJson, InspectionItemTitleDto.class); |
| 100 | 104 | ... | ... |