From fd832e23fd1d5395d385d92dad0a31d59fb6d95d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 22 Apr 2024 23:31:50 +0800 Subject: [PATCH 1/2] =?UTF-8?q?bugfix=EF=BC=9A=E9=9D=9E=20json=20=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=EF=BC=88=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=EF=BC=89?= =?UTF-8?q?=E6=97=B6=EF=BC=8Ctoken=20=E8=BF=87=E6=9C=9F=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E8=AF=BB=E5=8F=96=20request=20body=20?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/servlet/ServletUtils.java | 12 ++++++++++-- .../src/test/resources/sql/clean.sql | 1 - .../src/test/resources/sql/create_tables.sql | 15 --------------- .../dal/mysql/oauth2/OAuth2AccessTokenMapper.java | 2 ++ .../src/main/resources/application-local.yaml | 3 ++- yudao-server/src/main/resources/application.yaml | 1 - 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java index bc592d890..00b4687d4 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -93,11 +93,19 @@ public class ServletUtils { } public static String getBody(HttpServletRequest request) { - return JakartaServletUtil.getBody(request); + // 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取 + if (isJsonRequest(request)) { + return JakartaServletUtil.getBody(request); + } + return null; } public static byte[] getBodyBytes(HttpServletRequest request) { - return JakartaServletUtil.getBodyBytes(request); + // 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取 + if (isJsonRequest(request)) { + return JakartaServletUtil.getBodyBytes(request); + } + return null; } public static String getClientIP(HttpServletRequest request) { diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql index a3e0fd029..58345edd8 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql @@ -6,7 +6,6 @@ DELETE FROM "infra_job_log"; DELETE FROM "infra_api_access_log"; DELETE FROM "infra_api_error_log"; DELETE FROM "infra_file_config"; -DELETE FROM "infra_test_demo"; DELETE FROM "infra_data_source_config"; DELETE FROM "infra_codegen_table"; DELETE FROM "infra_codegen_column"; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql index 9f383ac5a..d4ca2b80e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql @@ -146,21 +146,6 @@ CREATE TABLE IF NOT EXISTS "infra_api_error_log" ( primary key ("id") ) COMMENT '系统异常日志'; -CREATE TABLE IF NOT EXISTS "infra_test_demo" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "name" varchar(100) NOT NULL, - "status" tinyint NOT NULL, - "type" tinyint NOT NULL, - "category" tinyint NOT NULL, - "remark" varchar(500), - "creator" varchar(64) DEFAULT '''', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '''', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '字典类型表'; - CREATE TABLE IF NOT EXISTS "infra_data_source_config" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "name" varchar(100) NOT NULL, diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2AccessTokenMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2AccessTokenMapper.java index 8a1e2876d..81ca13fad 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2AccessTokenMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2AccessTokenMapper.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.oauth2; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import org.apache.ibatis.annotations.Mapper; @@ -13,6 +14,7 @@ import java.util.List; @Mapper public interface OAuth2AccessTokenMapper extends BaseMapperX { + @TenantIgnore // 获取 token 的时候,需要忽略租户编号。原因是:一些场景下,可能不会传递 tenant-id 请求头,例如说文件上传、积木报表等等 default OAuth2AccessTokenDO selectByAccessToken(String accessToken) { return selectOne(OAuth2AccessTokenDO::getAccessToken, accessToken); } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 328e9c27b..7f348da84 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -165,10 +165,11 @@ logging: # 配置自己写的 MyBatis Mapper 打印日志 cn.iocoder.yudao.module.bpm.dal.mysql: debug cn.iocoder.yudao.module.infra.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info,避免和 GlobalExceptionHandler 重复打印 cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info cn.iocoder.yudao.module.pay.dal.mysql: debug - cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 JobLogMapper 的日志级别为 info + cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info cn.iocoder.yudao.module.system.dal.mysql: debug cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info cn.iocoder.yudao.module.tool.dal.mysql: debug diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index ae336f429..6cb5386e3 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -211,7 +211,6 @@ yudao: - system_notify_template - infra_codegen_column - infra_codegen_table - - infra_test_demo - infra_config - infra_file_config - infra_file From 7f0485e872ca78e6b98e8bbfa1a9af39da475611 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 23 Apr 2024 09:41:10 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=A7=86=E9=A2=91=E5=9C=B0=E5=9D=80=E5=9C=A8?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E7=AB=AF=E6=92=AD=E6=94=BE=E7=9A=84=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=E6=80=A7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/servlet/ServletUtils.java | 18 ------------ .../admin/codegen/CodegenController.java | 14 +++++----- .../controller/admin/file/FileController.java | 4 +-- .../file/core/utils/FileTypeUtils.java | 28 +++++++++++++++++++ 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java index 00b4687d4..12731edad 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.common.util.servlet; -import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.JakartaServletUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -12,8 +11,6 @@ import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import java.io.IOException; -import java.net.URLEncoder; import java.util.Map; /** @@ -35,21 +32,6 @@ public class ServletUtils { JakartaServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE); } - /** - * 返回附件 - * - * @param response 响应 - * @param filename 文件名 - * @param content 附件内容 - */ - public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException { - // 设置 header 和 contentType - response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); - // 输出附件 - IoUtil.write(response.getOutputStream(), false, content); - } - /** * @param request 请求 * @return ua diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java index 356bb4139..ed4c34446 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java @@ -5,7 +5,6 @@ import cn.hutool.core.util.ZipUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenCreateListReqVO; import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenDetailRespVO; import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenPreviewRespVO; @@ -17,17 +16,17 @@ import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; import cn.iocoder.yudao.module.infra.service.codegen.CodegenService; -import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -36,6 +35,7 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment; @Tag(name = "管理后台 - 代码生成器") @RestController @@ -145,7 +145,7 @@ public class CodegenController { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ZipUtil.zip(outputStream, paths, ins); // 输出 - ServletUtils.writeAttachment(response, "codegen.zip", outputStream.toByteArray()); + writeAttachment(response, "codegen.zip", outputStream.toByteArray()); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index bbd29dc29..2f92adc0e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -6,7 +6,6 @@ import cn.hutool.core.util.URLUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.service.file.FileService; @@ -26,6 +25,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment; @Tag(name = "管理后台 - 文件存储") @RestController @@ -88,7 +88,7 @@ public class FileController { response.setStatus(HttpStatus.NOT_FOUND.value()); return; } - ServletUtils.writeAttachment(response, path, content); + writeAttachment(response, path, content); } @GetMapping("/page") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java index ea71f5881..8970c004c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java @@ -1,9 +1,15 @@ package cn.iocoder.yudao.module.infra.framework.file.core.utils; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.ttl.TransmittableThreadLocal; +import jakarta.servlet.http.HttpServletResponse; import lombok.SneakyThrows; import org.apache.tika.Tika; +import java.io.IOException; +import java.net.URLEncoder; + /** * 文件类型 Utils * @@ -45,4 +51,26 @@ public class FileTypeUtils { return TIKA.get().detect(data, name); } + /** + * 返回附件 + * + * @param response 响应 + * @param filename 文件名 + * @param content 附件内容 + */ + public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException { + // 设置 header 和 contentType + response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + String contentType = getMineType(content, filename); + response.setContentType(contentType); + // 针对 video 的特殊处理,解决视频地址在移动端播放的兼容性问题 + if (StrUtil.containsIgnoreCase(contentType, "video")) { + response.setHeader("Content-Length", String.valueOf(content.length - 1)); + response.setHeader("Content-Range", String.valueOf(content.length - 1)); + response.setHeader("Accept-Ranges", "bytes"); + } + // 输出附件 + IoUtil.write(response.getOutputStream(), false, content); + } + }