Просмотр исходного кода

更新缩略图生成逻辑,支持不同类型的缩略图生成;修改配置文件以添加 MinIO 基础 URL

xiaoyelj 5 месяцев назад
Родитель
Сommit
2b25caee5c

+ 1 - 1
.gitignore

@@ -5,7 +5,7 @@ target/
 
 ### IntelliJ IDEA ###
 .idea
-
+logs
 *.iws
 *.iml
 *.ipr

+ 0 - 10
.idea/.gitignore

@@ -1,10 +0,0 @@
-# 默认忽略的文件
-/shelf/
-/workspace.xml
-# 基于编辑器的 HTTP 客户端请求
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
-
-.idea

+ 0 - 5
.idea/codeStyles/codeStyleConfig.xml

@@ -1,5 +0,0 @@
-<component name="ProjectCodeStyleConfiguration">
-  <state>
-    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
-  </state>
-</component>

+ 0 - 8
.idea/encodings.xml

@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="Encoding">
-    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/src/main/kotlin" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
-  </component>
-</project>

+ 0 - 6
.idea/kotlinc.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="KotlinJpsPluginSettings">
-    <option name="version" value="1.9.23" />
-  </component>
-</project>

+ 0 - 14
.idea/misc.xml

@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ExternalStorageConfigurationManager" enabled="true" />
-  <component name="MavenProjectsManager">
-    <option name="originalFiles">
-      <list>
-        <option value="$PROJECT_DIR$/pom.xml" />
-      </list>
-    </option>
-  </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
-    <output url="file://$PROJECT_DIR$/out" />
-  </component>
-</project>

+ 0 - 6
.idea/vcs.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="VcsDirectoryMappings">
-    <mapping directory="$PROJECT_DIR$" vcs="Git" />
-  </component>
-</project>

+ 1 - 26
API-USAGE.md

@@ -23,37 +23,12 @@
 
 ```bash
 # 基本用法
-curl "http://localhost:8080/api/thumbnail/generate?path=photos/sunset.jpg&w=300&h=300" \
+curl "http://localhost:8080/api/thumbnail/{path}&w=300&h=300" \
   --output thumbnail.jpg
 
-# 使用默认尺寸
-curl "http://localhost:8080/api/thumbnail/generate?path=images/photo.png" \
-  --output thumbnail.jpg
-
-# 生成不同尺寸
-curl "http://localhost:8080/api/thumbnail/generate?path=gallery/image.jpg&w=150&h=150" \
-  --output small_thumbnail.jpg
-```
 
 ### 响应说明
 
-**成功响应**:
-- **状态码**: 200
-- **Content-Type**: `image/jpeg`
-- **Cache-Control**: `max-age=3600`
-- **响应体**: JPG格式的图片二进制数据
-
-**错误响应**:
-- **状态码**: 500
-- **Content-Type**: `application/json`
-- **响应体**:
-```json
-{
-  "success": false,
-  "message": "错误信息"
-}
-```
-
 ### 常见错误
 
 | 错误信息 | 原因 | 解决方案 |

+ 0 - 304
logs/solon.log

@@ -1,304 +0,0 @@
-INFO  2025-08-07 13:14:07.688 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:14:07.691 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:14:07.693 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:14:07.698 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:14:07.970 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:14:07.970 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @214ms
-INFO  2025-08-07 13:14:07.972 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=945ms pid=19436 v=3.2.0
-INFO  2025-08-07 13:14:10.989 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:14:10.993 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:15:40.323 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:15:40.326 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:15:40.329 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:15:40.334 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:15:40.606 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:15:40.606 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @209ms
-INFO  2025-08-07 13:15:40.607 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=970ms pid=20760 v=3.2.0
-INFO  2025-08-07 13:16:56.311 [-smarthttp-3][*][c.y.t.c.ThumbnailController]: 
-开始生成缩略图: 路径=a, 尺寸=0x0
-WARN  2025-08-07 13:16:56.329 [-smarthttp-3][*][o.noear.solon.Solon]: 
-SolonApp tryHandle failed!
-java.lang.IllegalArgumentException: 宽度必须在1-4000像素之间
-	at com.yujin.thumbnail.controller.ThumbnailController.generateThumbnail(ThumbnailController.kt:29)
-	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
-	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
-	at org.noear.solon.core.wrap.MethodWrap.invoke(MethodWrap.java:269)
-	at org.noear.solon.core.wrap.MethodWrap.doIntercept(MethodWrap.java:258)
-	at org.noear.solon.core.aspect.InterceptorEntity.doIntercept(InterceptorEntity.java:55)
-	at org.noear.solon.core.aspect.Invocation.invoke(Invocation.java:115)
-	at org.noear.solon.core.wrap.MethodWrap.invokeByAspect(MethodWrap.java:284)
-	at org.noear.solon.core.mvc.ActionDefault.executeDo(ActionDefault.java:391)
-	at org.noear.solon.core.mvc.ActionDefault.invokeMethodDo(ActionDefault.java:327)
-	at org.noear.solon.core.mvc.ActionDefault.invokeHandleDo(ActionDefault.java:304)
-	at org.noear.solon.core.handle.FilterChainImpl.doFilter(FilterChainImpl.java:51)
-	at org.noear.solon.core.mvc.ActionDefault.invokeFilterDo(ActionDefault.java:296)
-	at org.noear.solon.core.handle.FilterChainImpl.doFilter(FilterChainImpl.java:51)
-	at org.noear.solon.core.mvc.ActionDefault.invoke(ActionDefault.java:270)
-	at org.noear.solon.core.mvc.ActionDefault.handle(ActionDefault.java:247)
-	at org.noear.solon.core.route.RouterHandler.handleMain(RouterHandler.java:51)
-	at org.noear.solon.core.route.RouterHandler.handle1(RouterHandler.java:71)
-	at org.noear.solon.core.route.RouterInterceptorChainImpl.doIntercept(RouterInterceptorChainImpl.java:54)
-	at org.noear.solon.core.ChainManager.doIntercept(ChainManager.java:199)
-	at org.noear.solon.core.route.RouterHandler.handle(RouterHandler.java:102)
-	at org.noear.solon.core.handle.HandlerPipeline.handle(HandlerPipeline.java:53)
-	at org.noear.solon.core.handle.FilterChainImpl.doFilter(FilterChainImpl.java:51)
-	at org.noear.solon.logging.integration.LoggingPlugin.lambda$start$1(LoggingPlugin.java:71)
-	at org.noear.solon.core.handle.FilterChainImpl.doFilter(FilterChainImpl.java:49)
-	at org.noear.solon.core.ChainManager.doFilter(ChainManager.java:106)
-	at org.noear.solon.SolonApp.tryHandle(SolonApp.java:526)
-	at org.noear.solon.boot.smarthttp.http.SmHttpContextHandler.handleDo(SmHttpContextHandler.java:123)
-	at org.noear.solon.boot.smarthttp.http.SmHttpContextHandler.handle0(SmHttpContextHandler.java:101)
-	at org.noear.solon.boot.smarthttp.http.SmHttpContextHandler.lambda$handle$0(SmHttpContextHandler.java:86)
-	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
-	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
-	at java.base/java.lang.Thread.run(Thread.java:833)
-INFO  2025-08-07 13:28:51.481 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:28:51.484 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:28:55.024 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:28:55.027 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:28:55.029 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:28:55.034 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:28:55.294 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:28:55.294 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @193ms
-INFO  2025-08-07 13:28:55.296 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=874ms pid=10136 v=3.2.0
-INFO  2025-08-07 13:29:25.442 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:29:25.445 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:29:29.088 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:29:29.091 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:29:29.094 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:29:29.099 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:29:29.344 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:29:29.345 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @187ms
-INFO  2025-08-07 13:29:29.346 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=1012ms pid=22620 v=3.2.0
-INFO  2025-08-07 13:31:51.115 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:31:51.119 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:31:54.704 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:31:54.708 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:31:54.712 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:31:54.717 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:31:54.999 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:31:54.999 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @215ms
-INFO  2025-08-07 13:31:55.000 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=1001ms pid=22336 v=3.2.0
-INFO  2025-08-07 13:37:13.067 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:37:13.070 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:37:15.530 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:37:15.532 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:37:15.534 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:37:15.540 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:37:15.815 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:37:15.816 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @211ms
-INFO  2025-08-07 13:37:15.818 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=863ms pid=18516 v=3.2.0
-INFO  2025-08-07 13:38:11.018 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:38:11.021 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:38:51.903 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:38:51.905 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:38:51.908 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:38:51.914 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:38:52.188 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:38:52.189 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @211ms
-INFO  2025-08-07 13:38:52.191 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=851ms pid=21628 v=3.2.0
-INFO  2025-08-07 13:40:01.453 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:40:01.456 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:40:04.873 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:40:04.875 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:40:04.878 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:40:04.882 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:40:05.145 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:40:05.146 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @202ms
-INFO  2025-08-07 13:40:05.147 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=883ms pid=12672 v=3.2.0
-INFO  2025-08-07 13:43:23.575 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:43:23.575 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:43:27.022 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:43:27.025 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:43:27.027 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:43:27.033 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:43:27.342 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:43:27.342 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @234ms
-INFO  2025-08-07 13:43:27.343 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=994ms pid=12616 v=3.2.0
-INFO  2025-08-07 13:44:46.418 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:44:46.422 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:44:50.042 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:44:50.046 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:44:50.050 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:44:50.060 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:44:50.410 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:44:50.410 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @222ms
-INFO  2025-08-07 13:44:50.412 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=1056ms pid=23428 v=3.2.0
-INFO  2025-08-07 13:45:09.792 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:45:09.795 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:45:13.135 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:45:13.138 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:45:13.142 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:45:13.150 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:45:13.443 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:45:13.444 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @220ms
-INFO  2025-08-07 13:45:13.447 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=939ms pid=7492 v=3.2.0
-INFO  2025-08-07 13:45:20.158 [-smarthttp-1][*][c.y.t.c.ThumbnailController]: 
-开始生成缩略图: 路径=generate, 尺寸=100x100
-INFO  2025-08-07 13:45:43.401 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 13:45:43.404 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 13:45:46.945 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:45:46.947 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 13:45:46.951 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 13:45:46.958 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 13:45:47.256 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 13:45:47.256 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @223ms
-INFO  2025-08-07 13:45:47.259 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=1000ms pid=17924 v=3.2.0
-INFO  2025-08-07 14:53:13.349 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 14:53:13.353 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 14:53:17.244 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 14:53:17.247 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 14:53:17.250 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 14:53:17.254 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 14:53:17.551 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 14:53:17.552 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @239ms
-INFO  2025-08-07 14:53:17.554 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=891ms pid=19788 v=3.2.0
-INFO  2025-08-07 14:54:07.693 [-smarthttp-1][*][c.y.t.c.ThumbnailController]: 
-开始生成缩略图: 路径=/api/thumbnail/generate/133, 尺寸=100x100
-INFO  2025-08-07 14:54:36.739 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 14:54:36.742 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped
-INFO  2025-08-07 14:54:40.327 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @json=StringSerializerRender#snack3-json
-INFO  2025-08-07 14:54:40.330 [-main][*][o.noear.solon.Solon]: 
-Render mapping: @type_json=StringSerializerRender#snack3-json
-INFO  2025-08-07 14:54:40.333 [-main][*][o.noear.solon.Solon]: 
-Session: Local session state plugin is loaded
-INFO  2025-08-07 14:54:40.339 [-main][*][o.noear.solon.Solon]: 
-App: Bean scanning
-INFO  2025-08-07 14:54:40.644 [-main][*][o.noear.solon.Solon]: 
-solon.connector:main: smarthttp: Started ServerConnector@{HTTP/1.1,[http/1.1]}{http://localhost:8080}
-INFO  2025-08-07 14:54:40.645 [-main][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Started (smart http 2.5/3.2.0) @227ms
-INFO  2025-08-07 14:54:40.647 [-main][*][o.noear.solon.Solon]: 
-App: End loading elapsed=991ms pid=23452 v=3.2.0
-INFO  2025-08-07 14:54:53.563 [-smarthttp-2][*][c.y.t.c.ThumbnailController]: 
-开始生成缩略图: 路径=/generate/133, 尺寸=100x100
-INFO  2025-08-07 14:55:22.308 [-smarthttp-4][*][c.y.t.c.ThumbnailController]: 
-开始生成缩略图: 路径=/微信截图_20240820173307.png, 尺寸=100x100
-INFO  2025-08-07 14:55:44.025 [-smarthttp-4][*][c.y.t.s.ThumbnailService]: 
-生成新的缩略图: C:/Users/xiaoyelj/Pictures/千寻图片/微信截图_20240820173307.png -> C:\Users\xiaoyelj\Pictures\千寻图片\微信截图_20240820173307_100_100.jpg
-INFO  2025-08-07 14:56:07.303 [-smarthttp-4][*][c.y.t.c.ThumbnailController]: 
-缩略图生成并输出成功
-INFO  2025-08-07 15:06:50.909 [-Thread-0][*][o.noear.solon.Solon]: 
-Server:main: smarthttp: Has Stopped (smart http 2.5/3.2.0)
-INFO  2025-08-07 15:06:50.912 [-Thread-0][*][o.noear.solon.Solon]: 
-App: Stopped

+ 16 - 1
pom.xml

@@ -5,7 +5,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>com.yujin</groupId>
-    <artifactId>yujin-humbnailator</artifactId>
+    <artifactId>yujin-thumbnailator</artifactId>
     <version>1.0-SNAPSHOT</version>
 
     <properties>
@@ -47,6 +47,11 @@
             <version>0.4.20</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.noear</groupId>
+            <artifactId>solon-net-httputils</artifactId>
+        </dependency>
+
         <!-- Kotlin Standard Library -->
         <dependency>
             <groupId>org.jetbrains.kotlin</groupId>
@@ -102,6 +107,16 @@
                 </configuration>
             </plugin>
 
+            <!-- 配置打包插件(并打包成胖包) -->
+            <plugin>
+                <groupId>org.noear</groupId>
+                <artifactId>solon-maven-plugin</artifactId>
+                <configuration>
+                    <!-- 指定启动主类 -->
+                    <mainClass>com.yujin.thumbnail.ThumbnailApplication</mainClass>
+                </configuration>
+            </plugin>
+
             <!-- Maven Compiler Plugin -->
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>

+ 2 - 0
script/prod-deploy.ps1

@@ -0,0 +1,2 @@
+scp ../target/*.jar root@10.0.0.130:/data/thumbnail/build
+ssh root@10.0.0.130 "cd /data/thumbnail/build && ./build.sh && ./startup.sh"

+ 2 - 0
script/test-deploy.ps1

@@ -0,0 +1,2 @@
+scp ../target/*.jar root@10.0.1.48:/app/dockerbuild/thumbnailator/build
+ssh root@10.0.1.48 "cd /app/dockerbuild/thumbnailator/build && ./build.sh && ./startup.sh"

+ 9 - 8
src/main/kotlin/com/yujin/thumbnail/ThumbnailApplication.kt

@@ -1,14 +1,15 @@
 package com.yujin.thumbnail
 
 import org.noear.solon.Solon
+import org.noear.solon.annotation.SolonMain
+
+@SolonMain
+class ThumbnailApplication {
+    companion object {
+        @JvmStatic
+        fun main(args: Array<String>) {
+            Solon.start(ThumbnailApplication::class.java, args)
+        }
 
-/**
- * 缩略图生成应用程序主类
- */
-fun main(args: Array<String>) {
-    Solon.start(ThumbnailApplication::class.java, args) {
-        // 配置文件上传大小限制
     }
 }
-
-class ThumbnailApplication

+ 3 - 2
src/main/kotlin/com/yujin/thumbnail/controller/ThumbnailController.kt

@@ -24,13 +24,14 @@ class ThumbnailController {
     fun generateThumbnail(
         @Param("w") w: Int = 200,
         @Param("h") h: Int = 200,
+        @Param("t") t: String = "1",
     ) {
         var path = Context.current().path().substring("/api/thumbnail".length)
-        logger.info("开始生成缩略图: 路径={}, 尺寸={}x{}", path, w, h) // 验证参数
+        logger.info("请求参数: 路径=${path}, 尺寸=${w}x${h}_${t}") // 验证参数
         require(path.isNotBlank()) { "文件路径不能为空" }
         require(w > 0 && w <= 4000) { "宽度必须在1-4000像素之间" }
         require(h > 0 && h <= 4000) { "高度必须在1-4000像素之间" } // 直接将缩略图写入响应流
-        thumbnailService.generateThumbnailToStream(path, w, h)
+        thumbnailService.generateThumbnailToStream(path, w, h,t)
         logger.info("缩略图生成并输出成功")
 
     }

+ 28 - 16
src/main/kotlin/com/yujin/thumbnail/service/ThumbnailService.kt

@@ -6,8 +6,10 @@ import net.coobird.thumbnailator.geometry.Positions
 import org.noear.solon.annotation.Component
 import org.noear.solon.annotation.Inject
 import org.noear.solon.core.handle.Context
+import org.noear.solon.net.http.HttpUtils
 import java.awt.Color
 import java.io.*
+import java.net.URL
 import java.nio.file.Files
 
 /**
@@ -23,6 +25,9 @@ class ThumbnailService {
     @Inject("\${thumbnai.filePrefix}")
     private lateinit var filePrefix: String
 
+    @Inject("\${thumbnai.minioBaseUrl}")
+    private lateinit var minioBaseUrl: String
+
 
     /**
      * 基于文件路径生成缩略图并直接写入输出流
@@ -31,42 +36,49 @@ class ThumbnailService {
      * @param height 目标高度
      * @param outputStream 输出流
      */
-    fun generateThumbnailToStream(relativePath: String, width: Int, height: Int) { // 构建完整的文件路径
+    fun generateThumbnailToStream(relativePath: String, width: Int, height: Int, type: String) { // 构建完整的文件路径
         val fullPath = filePrefix + relativePath
-        val sourceFile = File(fullPath)
-
-        // 验证源文件是否存在
-        require(sourceFile.exists()) { "源文件不存在: $fullPath" }
-        require(sourceFile.isFile) { "路径不是一个文件: $fullPath" }
 
         // 构建缩略图文件路径
-        val thumbnailPath = buildThumbnailPath(fullPath, width, height)
+        val thumbnailPath = buildThumbnailPath(fullPath, width, height, type)
         val thumbnailFile = File(thumbnailPath)
 
         // 如果缩略图已存在,直接复制到输出流
-        if (!thumbnailFile.exists()) { // 生成缩略图
-            logger.info("生成新的缩略图: {} -> {}", fullPath, thumbnailPath) // 确保缩略图目录存在
-            thumbnailFile.parentFile?.mkdirs() // 使用配置的质量生成缩略图
-            val thumbnailBuilder = Thumbnails.of(sourceFile)
-                .size(width,height)
-                .outputFormat("jpg").outputQuality(quality!!) // 先保存到文件(用于缓存)
+        if (!thumbnailFile.exists()) {
+            thumbnailFile.parentFile?.mkdirs()
+            // 生成缩略图
+            logger.info("生成新的缩略图: {} -> {}", relativePath, thumbnailPath)
+            // 使用配置的质量生成缩略图
+            val thumbnailBuilder = Thumbnails.of(URL("${minioBaseUrl}${relativePath}")).apply {
+                when (type) {
+                    "1" -> this.sourceRegion(Positions.CENTER, width, height)
+                    "2" -> this.sourceRegion(Positions.TOP_LEFT, width, height)
+                    "3" -> this.sourceRegion(Positions.TOP_CENTER, width, height)
+                    "4" -> this.sourceRegion(Positions.TOP_RIGHT, width, height)
+                    "5" -> this.sourceRegion(Positions.CENTER_LEFT, width, height)
+                    "6" -> this.sourceRegion(Positions.CENTER_RIGHT, width, height)
+                    "7" -> this.sourceRegion(Positions.BOTTOM_LEFT, width, height)
+                    "8" -> this.sourceRegion(Positions.BOTTOM_CENTER, width, height)
+                    "9" -> this.sourceRegion(Positions.BOTTOM_RIGHT, width, height)
+                }
+            }.size(width,height).outputFormat("jpg").outputQuality(quality!!) // 先保存到文件(用于缓存)
             thumbnailBuilder.toFile(thumbnailFile)
         }
         var context = Context.current()
-        context.headerAdd("content-Type", "application/")
+        context.headerAdd("content-Type", "image/jpeg")
         context.outputStream().use {
             Files.copy(thumbnailFile.toPath(), it)
         }
     }
 
 
-    private fun buildThumbnailPath(originalPath: String, width: Int, height: Int): String {
+    private fun buildThumbnailPath(originalPath: String, width: Int, height: Int, type: String): String {
         val file = File(originalPath)
         val directory = file.parent
         val nameWithoutExt = file.nameWithoutExtension
         val extension = "jpg"  // 固定为jpg格式
 
-        val thumbnailName = "${nameWithoutExt}_${width}_${height}.${extension}"
+        val thumbnailName = "${nameWithoutExt}_${width}_${height}_${type}.${extension}"
         return File(directory, thumbnailName).absolutePath
     }
 

+ 2 - 1
src/main/resources/app-dev.yml

@@ -5,4 +5,5 @@ solon.logging:
 
 thumbnai:
   filePrefix: C:/Users/xiaoyelj/Pictures/千寻图片
-  quality: 0.4
+  quality: 0.4
+  minioBaseUrl: http://10.0.1.48:9000

+ 6 - 1
src/main/resources/app-pro.yml

@@ -1,4 +1,9 @@
 solon.logging:
   appender:
     console:
-      level: INFO
+      level: INFO
+
+thumbnai:
+  filePrefix: /file-root
+  quality: 0.6
+  minioBaseUrl: http://10.0.0.130:9000

+ 4 - 0
src/main/resources/app-test.yml

@@ -2,3 +2,7 @@ solon.logging:
   appender:
     console:
       level: DEBUG
+
+thumbnai:
+  filePrefix: /file-root
+  quality: 0.6

+ 2 - 1
src/main/resources/app.yml

@@ -19,4 +19,5 @@ solon.serialization.json:
 
 thumbnai:
   filePrefix: /
-  quality: 0.4
+  quality: 0.4
+  minioBaseUrl: http://10.0.1.48:9000

+ 0 - 26
start-dev.bat

@@ -1,26 +0,0 @@
-@echo off
-echo ======================================
-echo 缩略图生成器 - 开发环境启动脚本
-echo ======================================
-
-echo 正在编译项目...
-call mvn clean compile
-
-if %ERRORLEVEL% neq 0 (
-    echo 编译失败,请检查错误信息
-    pause
-    exit /b 1
-)
-
-echo 编译成功,正在启动开发环境...
-echo 环境: development
-echo 端口: 8080
-echo 配置文件: application-dev.yml
-echo 访问地址: http://localhost:8080
-echo 测试页面: http://localhost:8080/index.html
-echo.
-echo 按 Ctrl+C 停止应用
-echo ======================================
-
-set SPRING_PROFILES_ACTIVE=dev
-call mvn exec:java -Dexec.mainClass="com.yujin.thumbnail.ThumbnailApplicationKt" -Dspring.profiles.active=dev

+ 0 - 26
start-prod.bat

@@ -1,26 +0,0 @@
-@echo off
-echo ======================================
-echo 缩略图生成器 - 生产环境启动脚本
-echo ======================================
-
-echo 正在编译项目...
-call mvn clean compile
-
-if %ERRORLEVEL% neq 0 (
-    echo 编译失败,请检查错误信息
-    pause
-    exit /b 1
-)
-
-echo 编译成功,正在启动生产环境...
-echo 环境: production
-echo 端口: 80
-echo 配置文件: application-prod.yml
-echo 访问地址: http://localhost
-echo.
-echo 注意:生产环境配置请确保端口80可用
-echo 按 Ctrl+C 停止应用
-echo ======================================
-
-set SPRING_PROFILES_ACTIVE=prod
-call mvn exec:java -Dexec.mainClass="com.yujin.thumbnail.ThumbnailApplicationKt" -Dspring.profiles.active=prod

+ 0 - 26
start-test.bat

@@ -1,26 +0,0 @@
-@echo off
-echo ======================================
-echo 缩略图生成器 - 测试环境启动脚本
-echo ======================================
-
-echo 正在编译项目...
-call mvn clean compile
-
-if %ERRORLEVEL% neq 0 (
-    echo 编译失败,请检查错误信息
-    pause
-    exit /b 1
-)
-
-echo 编译成功,正在启动测试环境...
-echo 环境: test
-echo 端口: 8081
-echo 配置文件: application-test.yml
-echo 访问地址: http://localhost:8081
-echo 测试页面: http://localhost:8081/index.html
-echo.
-echo 按 Ctrl+C 停止应用
-echo ======================================
-
-set SPRING_PROFILES_ACTIVE=test
-call mvn exec:java -Dexec.mainClass="com.yujin.thumbnail.ThumbnailApplicationKt" -Dspring.profiles.active=test

+ 0 - 14
start.bat

@@ -1,14 +0,0 @@
-@echo off
-echo ======================================
-echo 缩略图生成器启动脚本(默认开发环境)
-echo ======================================
-echo.
-echo 可用的启动脚本:
-echo   start-dev.bat  - 开发环境 (端口: 8080)
-echo   start-test.bat - 测试环境 (端口: 8081)
-echo   start-prod.bat - 生产环境 (端口: 80)
-echo.
-echo 正在启动开发环境...
-echo ======================================
-
-call start-dev.bat