fix(infra): 修复文件名包含 + 号时预签名 URL 解码错误

This commit is contained in:
YunaiV
2026-03-07 19:24:10 +08:00
parent ba6cdabe62
commit c88f33c919
2 changed files with 18 additions and 2 deletions

View File

@@ -37,8 +37,10 @@ public class HttpUtils {
}
/**
* 解码 URL 参数
* 解码 URL 参数query parameter
* 注意:此方法会将 + 解码为空格,适用于 query parameter不适用于 URL path
*
* @see #decodeUrlPath(String)
* @param value 参数
* @return 解码后的参数
*/
@@ -46,6 +48,20 @@ public class HttpUtils {
return URLDecoder.decode(value, StandardCharsets.UTF_8);
}
/**
* 解码 URL 路径
* 与 {@link #decodeUtf8(String)} 不同,此方法不会将 + 解码为空格,保持 + 为字面字符
* 适用于 URL path 部分的解码
*
* @param path URL 路径
* @return 解码后的路径
*/
public static String decodeUrlPath(String path) {
// 先将 + 替换为 %2B避免被 URLDecoder 解码为空格
String encoded = path.replace("+", "%2B");
return URLDecoder.decode(encoded, StandardCharsets.UTF_8);
}
@SuppressWarnings("unchecked")
public static String replaceUrlQuery(String url, String key, String value) {
UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset());

View File

@@ -116,7 +116,7 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
public String presignGetUrl(String url, Integer expirationSeconds) {
// 1. 将 url 转换为 path
String path = StrUtil.removePrefix(url, config.getDomain() + "/");
path = HttpUtils.decodeUtf8(HttpUtils.removeUrlQuery(path));
path = HttpUtils.decodeUrlPath(HttpUtils.removeUrlQuery(path));
// 2.1 情况一:公开访问:无需签名
// 考虑到老版本的兼容,所以必须是 config.getEnablePublicAccess() 为 false 时,才进行签名