diff --git a/sdk/common/src/main/java/io/dataease/utils/HttpClientUtil.java b/sdk/common/src/main/java/io/dataease/utils/HttpClientUtil.java index 00bf0480ce..d2f962a6d5 100755 --- a/sdk/common/src/main/java/io/dataease/utils/HttpClientUtil.java +++ b/sdk/common/src/main/java/io/dataease/utils/HttpClientUtil.java @@ -5,6 +5,7 @@ import lombok.Data; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; @@ -38,6 +39,9 @@ import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.security.cert.X509Certificate; import java.util.*; import java.util.regex.Matcher; @@ -395,14 +399,14 @@ public class HttpClientUtil { } throw new Exception(msg); } - String fileName = extractFileName(response, url); - String suffix = fileName.substring(fileName.lastIndexOf(".") + 1); + String fileName = normalizeDownloadFileName(extractFileName(response, url)); + String suffix = extractSuffix(fileName); String tranName = UUID.randomUUID().toString() + "." + suffix; name.put("fileName", fileName); name.put("tranName", tranName); - File localFile = new File(path + tranName); + Path localFile = resolveDownloadPath(path, tranName); try (InputStream is = response.getEntity().getContent(); - FileOutputStream outputStream = new FileOutputStream(localFile)) { + OutputStream outputStream = Files.newOutputStream(localFile)) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { @@ -417,15 +421,26 @@ public class HttpClientUtil { } private static String extractFileName(HttpResponse response, String url) { - url = URLDecoder.decode(url); - String fileName = ""; - String disposition = response.getHeaders("Content-Disposition").toString(); - if (disposition != null) { - int filenameIndex = disposition.indexOf("filename="); - if (filenameIndex > 0) { - fileName = disposition.substring(filenameIndex + 9) - .replaceAll("\"", "") // 去除引号 - .trim(); + url = URLDecoder.decode(url, StandardCharsets.UTF_8); + String fileName = StringUtils.EMPTY; + Header dispositionHeader = response.getFirstHeader("Content-Disposition"); + if (dispositionHeader != null && StringUtils.isNotBlank(dispositionHeader.getValue())) { + String disposition = dispositionHeader.getValue(); + int filenameStarIndex = disposition.indexOf("filename*="); + if (filenameStarIndex >= 0) { + fileName = disposition.substring(filenameStarIndex + 10).trim(); + int charsetIndex = fileName.indexOf("''"); + if (charsetIndex >= 0) { + fileName = fileName.substring(charsetIndex + 2); + } + fileName = URLDecoder.decode(fileName.replace("\"", "").trim(), StandardCharsets.UTF_8); + } else { + int filenameIndex = disposition.indexOf("filename="); + if (filenameIndex >= 0) { + fileName = disposition.substring(filenameIndex + 9) + .replace("\"", "") + .trim(); + } } } if (fileName.isEmpty()) { @@ -434,12 +449,43 @@ public class HttpClientUtil { ? url.substring(url.lastIndexOf('/') + 1) : "download_" + System.currentTimeMillis(); } - if (fileName.trim().isEmpty()) { - fileName = "download_" + System.currentTimeMillis(); - } return fileName; } + private static String normalizeDownloadFileName(String fileName) { + String normalizedFileName = StringUtils.trimToEmpty(fileName); + if (normalizedFileName.isEmpty()) { + normalizedFileName = "download_" + System.currentTimeMillis(); + } + int separatorIndex = Math.max(normalizedFileName.lastIndexOf('/'), normalizedFileName.lastIndexOf('\\')); + if (separatorIndex >= 0) { + normalizedFileName = normalizedFileName.substring(separatorIndex + 1); + } + if (normalizedFileName.isEmpty()) { + normalizedFileName = "download_" + System.currentTimeMillis(); + } + FileUtils.validateUploadFilename(normalizedFileName); + return normalizedFileName; + } + + private static String extractSuffix(String fileName) { + int suffixIndex = fileName.lastIndexOf("."); + if (suffixIndex < 0 || suffixIndex == fileName.length() - 1) { + return "bin"; + } + return fileName.substring(suffixIndex + 1); + } + + private static Path resolveDownloadPath(String path, String fileName) { + FileUtils.validateUploadFilename(fileName); + Path directory = Paths.get(path).toAbsolutePath().normalize(); + Path target = directory.resolve(fileName).normalize(); + if (!target.startsWith(directory)) { + DEException.throwException("invalid download path"); + } + return target; + } + public static byte[] downloadBytes(String url) { HttpClientConfig config = new HttpClientConfig(); return HttpClientUtil.downFromRemote(url, config);