Commit c88f33c919666907020240a1dd3346810101e226
1 parent
ba6cdabe
fix(infra): 修复文件名包含 + 号时预签名 URL 解码错误
Showing
2 changed files
with
18 additions
and
2 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java
| @@ -37,8 +37,10 @@ public class HttpUtils { | @@ -37,8 +37,10 @@ public class HttpUtils { | ||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | /** | 39 | /** |
| 40 | - * 解码 URL 参数 | 40 | + * 解码 URL 参数(query parameter) |
| 41 | + * 注意:此方法会将 + 解码为空格,适用于 query parameter,不适用于 URL path | ||
| 41 | * | 42 | * |
| 43 | + * @see #decodeUrlPath(String) | ||
| 42 | * @param value 参数 | 44 | * @param value 参数 |
| 43 | * @return 解码后的参数 | 45 | * @return 解码后的参数 |
| 44 | */ | 46 | */ |
| @@ -46,6 +48,20 @@ public class HttpUtils { | @@ -46,6 +48,20 @@ public class HttpUtils { | ||
| 46 | return URLDecoder.decode(value, StandardCharsets.UTF_8); | 48 | return URLDecoder.decode(value, StandardCharsets.UTF_8); |
| 47 | } | 49 | } |
| 48 | 50 | ||
| 51 | + /** | ||
| 52 | + * 解码 URL 路径 | ||
| 53 | + * 与 {@link #decodeUtf8(String)} 不同,此方法不会将 + 解码为空格,保持 + 为字面字符 | ||
| 54 | + * 适用于 URL path 部分的解码 | ||
| 55 | + * | ||
| 56 | + * @param path URL 路径 | ||
| 57 | + * @return 解码后的路径 | ||
| 58 | + */ | ||
| 59 | + public static String decodeUrlPath(String path) { | ||
| 60 | + // 先将 + 替换为 %2B,避免被 URLDecoder 解码为空格 | ||
| 61 | + String encoded = path.replace("+", "%2B"); | ||
| 62 | + return URLDecoder.decode(encoded, StandardCharsets.UTF_8); | ||
| 63 | + } | ||
| 64 | + | ||
| 49 | @SuppressWarnings("unchecked") | 65 | @SuppressWarnings("unchecked") |
| 50 | public static String replaceUrlQuery(String url, String key, String value) { | 66 | public static String replaceUrlQuery(String url, String key, String value) { |
| 51 | UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset()); | 67 | UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset()); |
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java
| @@ -116,7 +116,7 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | @@ -116,7 +116,7 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | ||
| 116 | public String presignGetUrl(String url, Integer expirationSeconds) { | 116 | public String presignGetUrl(String url, Integer expirationSeconds) { |
| 117 | // 1. 将 url 转换为 path | 117 | // 1. 将 url 转换为 path |
| 118 | String path = StrUtil.removePrefix(url, config.getDomain() + "/"); | 118 | String path = StrUtil.removePrefix(url, config.getDomain() + "/"); |
| 119 | - path = HttpUtils.decodeUtf8(HttpUtils.removeUrlQuery(path)); | 119 | + path = HttpUtils.decodeUrlPath(HttpUtils.removeUrlQuery(path)); |
| 120 | 120 | ||
| 121 | // 2.1 情况一:公开访问:无需签名 | 121 | // 2.1 情况一:公开访问:无需签名 |
| 122 | // 考虑到老版本的兼容,所以必须是 config.getEnablePublicAccess() 为 false 时,才进行签名 | 122 | // 考虑到老版本的兼容,所以必须是 config.getEnablePublicAccess() 为 false 时,才进行签名 |