使用Apache HttpClient5 Fluent:如何还原存储的MultipartEntity参数?
解决方法
一、直接从MultipartEntity获取参数(无需转byte[]后再解析)
如果还未将MultipartEntity转为byte[],可以直接从MultipartFormEntity(MultipartEntityBuilder.build()的返回类型)中提取参数,这是最直接高效的方式:
// 校验并转换类型 if (httpEntity instanceof MultipartFormEntity multipartFormEntity) { // 获取所有表单部件 List<FormPart> parts = multipartFormEntity.getParts(); for (FormPart part : parts) { String paramName = part.getName(); ContentType contentType = part.getContentType(); // 处理文本参数 if (ContentType.TEXT_PLAIN.isCompatible(contentType)) { String textValue = EntityUtils.toString(part.getBody(), StandardCharsets.UTF_8); System.out.printf("文本参数:%s = %s%n", paramName, textValue); } // 处理文件参数 else if (contentType.getMimeType().startsWith("image/") || ContentType.APPLICATION_OCTET_STREAM.isCompatible(contentType)) { String fileName = part.getFilename(); System.out.printf("文件参数:%s,文件名:%s%n", paramName, fileName); // 如需读取文件内容,可调用EntityUtils.toByteArray(part.getBody()) } } }
二、从存储的byte[]解析回Multipart参数
如果已经将byte[]存入数据库,需要先提前保存Multipart的boundary分隔符(生成MultipartEntity时获取),再用MultipartStream解析:
步骤1:生成MultipartEntity时保存boundary
HttpEntity httpEntity = MultipartEntityBuilder.create() .addTextBody("name", "张三", ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)) .addBinaryBody("file", new File("C:\\Users\\123\\Desktop\\QQ截图20231010143306.png")) .build(); // 获取并保存boundary(和byte[]一起存入数据库) String boundary = ((MultipartFormEntity) httpEntity).getBoundary();
步骤2:从数据库取出byte[]和boundary后解析
// 从数据库取出的字节数组和boundary byte[] multipartByteArray = /* 从数据库获取 */; String boundary = /* 从数据库获取 */; ByteArrayInputStream inputStream = new ByteArrayInputStream(multipartByteArray); MultipartStream multipartStream = new MultipartStream(inputStream, boundary.getBytes(StandardCharsets.UTF_8), null, StandardCharsets.UTF_8); LinkedMultiValueMap<String, Part> partMap = new LinkedMultiValueMap<>(); boolean hasNextPart = multipartStream.skipPreamble(); while (hasNextPart) { // 解析部件头部信息 Header[] headers = multipartStream.readHeaders(); String paramName = null; String fileName = null; ContentType contentType = null; for (Header header : headers) { if ("Content-Disposition".equalsIgnoreCase(header.getName())) { String headerValue = header.getValue(); // 匹配参数名 Matcher nameMatcher = Pattern.compile("name=\"([^\"]+)\"").matcher(headerValue); if (nameMatcher.find()) paramName = nameMatcher.group(1); // 匹配文件名 Matcher fileNameMatcher = Pattern.compile("filename=\"([^\"]+)\"").matcher(headerValue); if (fileNameMatcher.find()) fileName = fileNameMatcher.group(1); } else if ("Content-Type".equalsIgnoreCase(header.getName())) { contentType = ContentType.parse(header.getValue()); } } if (paramName != null) { // 读取部件内容 ByteArrayOutputStream partOut = new ByteArrayOutputStream(); multipartStream.readBodyData(partOut); byte[] partContent = partOut.toByteArray(); // 封装为自定义Part对象(可根据需求调整) Part part = new Part() { @Override public String getName() { return paramName; } public String getFilename() { return fileName; } public ContentType getContentType() { return contentType; } public byte[] getContent() { return partContent; } }; partMap.add(paramName, part); } hasNextPart = multipartStream.readBoundary(); } // 解析完成后,partMap即为参数映射
关键注意事项
- 存储byte[]时必须同步保存boundary,否则无法正确解析Multipart内容。
- 大文件建议只记录文件名、参数名、文件大小等元信息,避免数据库体积过载。
- 使用
EntityUtils处理流时,建议用try-with-resources确保资源释放。
内容的提问来源于stack exchange,提问作者1872386506
相关产品推荐
相关产品推荐

