web-dev-qa-db-ja.com

(Restクライアントから)RestTemplateを使用するときに、マルチパートアップロードでファイルのコンテンツタイプを設定する方法

アップロードしようとしているファイルは常にxmlファイルです。 content-typeを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」にしたいのですが、ファイルのコンテンツタイプを設定するにはどうすればよいですか?

19
RGR

このリンクからヒントを得た後、私は解決策を見つけました:

AndroidのSpringで圧縮されたjpegバイト配列を使用してマルチパート投稿リクエストを行う

解決策は、ByteArrayResourceを必要なヘッダーを含む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);
32
RGR

これは私がファイルのアップロードを処理し、アップロードされたファイルを受け取る方法です:

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()
        );
    }

}

RestTemplateを使用したことはありませんが、過去にHttpClientを使用したことがあります-これは、ボディパーツを渡す方法です-

MultipartEntityBuilder eb = MultipartEntityBuilder.create().setBoundary(MULTIPART_BOUNDARY)
                .addTextBody(BODYPART_ENTITY, key, ContentType.create("application/xml", Charset.forName("UTF-8")));

あなたは、コンテンツタイプを取ることができるRestTemplateでAPIを探す必要があります

0
Pankaj

@RGRの回答にコメントできないので、RGRの回答は完全に正しいですが、これを新しい回答として投稿しています。

問題は、Sprint RestTemplatesがFormHttpMessageConverterを使用してマルチパートリクエストを送信することです。このコンバーターは、R​​esourceから継承するすべてのものを検出し、これを要求の「ファイル」部分として使用します。例えばMultiValueMapを使用する場合、「リソース」を追加するとすぐに、追加するすべてのプロパティが独自の部分で送信されます...-->設定ファイル名、MIMEタイプ、長さなどは、「ファイル」の一部ではありません。部"。

答えではありませんが、ByteArrayResourceを拡張してファイル名を返し、リクエストの唯一の部分として送信する必要があるのはそのためです。複数のファイルを送信すると、MultiValueMapで機能します

この動作はSpring 4.3で SPR-13571 によって修正されたようです

0