背景
在一个项目里,需要对RestTemplate请求打印日志,包括请求报文、请求参数等内容。可是对于content-type为mutipart/form-data
类型的请求报文,打印日志的时候,格式非常奇怪。
分析
也能理解的,毕竟这个本身只是用来文件上传的,存在其它参数也需要读取出来,就不太容易。如果是在HttpServletRequest中读取个请求参数,那是相当easy,可这不是servlet,拿到的只是HttpRequest,请求参数没办法从HttpRequest中读取。那就只能采用下下策,对输出的字符串进行提取。我们可以注意到,输出的报文的字段,会通过content-type的boundary进行分割。先通过boundary分割字段,再进行关键文字提取。
public static Map<String, String> parseMultipartRequest(String requestBody, String contentTypeString) {
String boundary = extractBoundary(contentTypeString);
Map<String, String> formData = new HashMap<>();
String[] parts = requestBody.split("--" + boundary);
for (String part : parts) {
if (part.trim().isEmpty()) {
continue; // Skip empty parts
}
String[] headersAndContent = part.split("\r\n\r\n", 2);
String[] headers = headersAndContent[0].split("\r\n");
if (header.length < 2) continue;
String content = headersAndContent[1].trim();
Map<String, String> partData = extractPartData(headers, content);
formData.putAll(partData);
}
return formData;
}
private static Map<String, String> extractPartData(String[] headers, String content) {
Map<String, String> partData = new HashMap<>();
// Extract name from Content-Disposition header
String name = null;
for (String header : headers) {
if (header.startsWith("Content-Disposition")) {
name = header.split('name="')[1].split('"')[0];
break;
}
}
if (name != null) {
partData.put(name, content);
}
return partData;
}
private String extractBoundary(String contentType) {
String[] parts = contentType.split(";");
for (String part : parts) {
part = part.trim();
if (part.startsWith("boundary=")) {
return part.substring("boundary=".length());
}
}
throw new IllegalArgumentException("Boundary not found in Content-Type header");
}