使用 RestTemplate(来自休息客户端)时如何在分段上传中设置文件的内容类型
How to set content-type for the file in multipart upload when using RestTemplate (from a rest client)
我尝试上传的文件始终是 xml 文件。我想将内容类型设置为 application/xml
这是我的代码:
MultiValueMap<String, Object parts = new LinkedMultiValueMap<String,
Object(); parts.add("subject", "some info");
ByteArrayResource xmlFile = new ByteArrayResource(stringWithXMLcontent.getBytes("UTF-8")){
@Override
public String getFilename(){
return documentName;
}
};
parts.add("attachment", xmlFile);
//sending the request using RestTemplate template;, the request is successfull
String result = template.postForObject(getRestURI(), httpEntity,String.class);
//but the content-type of file is 'application/octet-stream'
原始请求如下所示:
Content-Type:
multipart/form-data;boundary=gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz
User-Agent: Java/1.7.0_67 Host: some.host Connection: keep-alive
Content-Length: 202866
--gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz Content-Disposition: form-data; name="subject" Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 19
some info
--gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz Content-Disposition: form-data; name="attachment"; filename="filename.xml" Content-Type:
application/octet-stream Content-Length: 201402
....xml file contents here ..
文件的内容类型生成为 'application/octet-stream',而我希望它是 'application/xml'
如何设置文件的内容类型?
我没有使用过 RestTemplate,但我过去使用过 HttpClient - 这就是我传递正文部分的方式 -
MultipartEntityBuilder eb = MultipartEntityBuilder.create().setBoundary(MULTIPART_BOUNDARY)
.addTextBody(BODYPART_ENTITY, key, ContentType.create("application/xml", Charset.forName("UTF-8")));
您将不得不在 RestTemplate 中查看 API,它可以采用内容类型
我从这个 link:
得到提示后找到了解决方案
Making a multipart post request with compressed jpeg byte array with spring for android
解决方案是将 ByteArrayResource 放入需要 header 的 HttpEntity 中,并将 HttpEntity 添加到 Multivaluemap(而不是添加 ByteArrayResource 本身。)
代码:
Resource xmlFile = new ByteArrayResource(stringWithXMLcontent.getBytes("UTF-8")){
@Override
public String getFilename(){
return documentName;
}
};
HttpHeaders xmlHeaders = new HttpHeaders();
xmlHeaders.setContentType(MediaType.APPLICATION_XML);
HttpEntity<Resource> xmlEntity = new HttpEntity<Resource>(xmlFile, xmlHeaders);
parts.add("attachment", xmlEntity);
由于我无法评论@RGR 的答案,所以我将其作为新答案发布,尽管 RGR 的答案是绝对正确的。
问题是,Sprint RestTemplates 使用 FormHttpMessageConverter 发送多部分请求。此转换器检测从 Resource 继承的所有内容,并将其用作请求的 "file" 部分。
例如如果您使用 MultiValueMap,您添加的每个 属性 将在您添加 "Resource" 后立即发送到它自己的部分...--> 设置文件名、Mime 类型、长度、.. 不会成为 "file part" 的一部分。
不是答案,但它解释了为什么 ByteArrayResource 必须扩展到 return 文件名并作为请求的唯一部分发送。发送多个文件将使用 MultiValueMap
看来此行为已在 Spring 4.3 中由 SPR-13571
修复
这是我处理文件上传和接收上传文件的方式:
public String uploadFile(byte[] fileContent, String contentType, String filename) {
String url = "https://localhost:8000/upload";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
ContentDisposition contentDisposition = ContentDisposition.builder("form-data")
.name("file")
.filename(filename)
.build();
fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
fileMap.add(HttpHeaders.CONTENT_TYPE, contentType);
HttpEntity<byte[]> entity = new HttpEntity<>(fileContent, fileMap);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", entity);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = template.exchange(url, HttpMethod.POST, requestEntity, String.class);
return response.getBody();
}
我这样使用它,服务监听在 8000 端口:
@Controller
@RequestMapping("upload")
public class FileUploadController {
@PostMapping("")
public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) {
handleUploadedFile(
file.getSize(),
file.getBytes(),
file.getContentType(),
file.getOriginalFilename()
);
}
}
我尝试上传的文件始终是 xml 文件。我想将内容类型设置为 application/xml 这是我的代码:
MultiValueMap<String, Object parts = new LinkedMultiValueMap<String,
Object(); parts.add("subject", "some info");
ByteArrayResource xmlFile = new ByteArrayResource(stringWithXMLcontent.getBytes("UTF-8")){
@Override
public String getFilename(){
return documentName;
}
};
parts.add("attachment", xmlFile);
//sending the request using RestTemplate template;, the request is successfull
String result = template.postForObject(getRestURI(), httpEntity,String.class);
//but the content-type of file is 'application/octet-stream'
原始请求如下所示:
Content-Type:
multipart/form-data;boundary=gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz
User-Agent: Java/1.7.0_67 Host: some.host Connection: keep-alive
Content-Length: 202866
--gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz Content-Disposition: form-data; name="subject" Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 19
some info
--gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz Content-Disposition: form-data; name="attachment"; filename="filename.xml" Content-Type:
application/octet-stream Content-Length: 201402
....xml file contents here ..
文件的内容类型生成为 'application/octet-stream',而我希望它是 'application/xml' 如何设置文件的内容类型?
我没有使用过 RestTemplate,但我过去使用过 HttpClient - 这就是我传递正文部分的方式 -
MultipartEntityBuilder eb = MultipartEntityBuilder.create().setBoundary(MULTIPART_BOUNDARY)
.addTextBody(BODYPART_ENTITY, key, ContentType.create("application/xml", Charset.forName("UTF-8")));
您将不得不在 RestTemplate 中查看 API,它可以采用内容类型
我从这个 link:
得到提示后找到了解决方案Making a multipart post request with compressed jpeg byte array with spring for android
解决方案是将 ByteArrayResource 放入需要 header 的 HttpEntity 中,并将 HttpEntity 添加到 Multivaluemap(而不是添加 ByteArrayResource 本身。)
代码:
Resource xmlFile = new ByteArrayResource(stringWithXMLcontent.getBytes("UTF-8")){
@Override
public String getFilename(){
return documentName;
}
};
HttpHeaders xmlHeaders = new HttpHeaders();
xmlHeaders.setContentType(MediaType.APPLICATION_XML);
HttpEntity<Resource> xmlEntity = new HttpEntity<Resource>(xmlFile, xmlHeaders);
parts.add("attachment", xmlEntity);
由于我无法评论@RGR 的答案,所以我将其作为新答案发布,尽管 RGR 的答案是绝对正确的。
问题是,Sprint RestTemplates 使用 FormHttpMessageConverter 发送多部分请求。此转换器检测从 Resource 继承的所有内容,并将其用作请求的 "file" 部分。 例如如果您使用 MultiValueMap,您添加的每个 属性 将在您添加 "Resource" 后立即发送到它自己的部分...--> 设置文件名、Mime 类型、长度、.. 不会成为 "file part" 的一部分。
不是答案,但它解释了为什么 ByteArrayResource 必须扩展到 return 文件名并作为请求的唯一部分发送。发送多个文件将使用 MultiValueMap
看来此行为已在 Spring 4.3 中由 SPR-13571
修复这是我处理文件上传和接收上传文件的方式:
public String uploadFile(byte[] fileContent, String contentType, String filename) {
String url = "https://localhost:8000/upload";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
ContentDisposition contentDisposition = ContentDisposition.builder("form-data")
.name("file")
.filename(filename)
.build();
fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
fileMap.add(HttpHeaders.CONTENT_TYPE, contentType);
HttpEntity<byte[]> entity = new HttpEntity<>(fileContent, fileMap);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", entity);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = template.exchange(url, HttpMethod.POST, requestEntity, String.class);
return response.getBody();
}
我这样使用它,服务监听在 8000 端口:
@Controller
@RequestMapping("upload")
public class FileUploadController {
@PostMapping("")
public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) {
handleUploadedFile(
file.getSize(),
file.getBytes(),
file.getContentType(),
file.getOriginalFilename()
);
}
}