如何使用Spring RestTemplate发送multipart/form-data请求?

huangapple go评论75阅读模式
英文:

How to send multipart/form-data with Spring RestTemplate?

问题

我想向一个 REST 端点发送 POST 请求。该 REST 端点的文档如下:

> 创建一个节点并将其添加为节点 nodeId 的主要子节点。
>
> 此端点支持 JSON 和 multipart/form-data(文件上传)两种方式。
>
> 使用 multipart/form-data
>
> 使用 filedata 字段来表示要上传的内容,例如,以下 curl 命令将在测试用户的主目录中创建一个带有 test.txt 内容的节点。
>
> curl -utest:test -X POST
> host:port/alfresco/api/-default-/public/alfresco/versions/1/nodes/-my-/children
> -F filedata=@test.txt
>
> 您可以使用 name 字段为新文件指定替代名称。
>
> 您可以使用 nodeType 字段创建特定类型。默认为 cm:content

我通过以下代码成功地向该端点发送了正确的请求:

@Override
public ResponseEntity<byte[]> postNode(String nodeId, byte[] content) {
  MultiValueMap<String, Object> bodyMap = new LinkedMultiValueMap<>();
  ByteArrayResource contentsAsResource = new ByteArrayResource(content) {
      @Override
      public String getFilename() {
          return "name22222";
      }
  };

  bodyMap.add("filedata", contentsAsResource);

  ///bodyMap.add("filedata", content);// 为什么这行不起作用?!

  HttpHeaders headers = new HttpHeaders();
  headers.setContentType(MediaType.MULTIPART_FORM_DATA);
  HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(bodyMap, headers);
  return restTemplate.exchange("/nodes/{nodeId}/children", HttpMethod.POST, requestEntity, byte[].class, nodeId);
}

但我有两个问题:

1 - 为什么注释掉的那行不起作用?

2 - 文档中说:

> 您可以使用 name 字段为新文件指定替代名称。

我没有使用 &quot;name&quot; 字段,但服务器将我的文件保存为正确的名称(=&quot;name22222&quot;),为什么?(我以为 multipart/form-data 是一种简单的名称-值方式,如果这是正确的,那么我有一个名为 "filedata" 的字段,其值是我的 byte 数组内容,那么文件名是如何发送的?)。我如何使用一个 字段 来指定文件名?

更新:
我认为我找到了答案。我只需要阅读关于 multipart/form-data 的内容!

英文:

I want to send a POST request to a rest endpoint. the rest endpoint documentation says:

> Create a node and add it as a primary child of node nodeId.
>
> This endpoint supports both JSON and multipart/form-data (file
> upload).
>
> Using multipart/form-data
>
> Use the filedata field to represent the content to upload, for
> example, the following curl command will create a node with the
> contents of test.txt in the test user's home folder.
>
> curl -utest:test -X POST
> host:port/alfresco/api/-default-/public/alfresco/versions/1/nodes/-my-/children
> -F filedata=@test.txt
>
> You can use the name field to give an alternative name for the new
> file.
>
> You can use the nodeType field to create a specific type. The default
> is cm:content

I managed to send a correct request to this endpoint by the following code:

@Override
public ResponseEntity&lt;byte[]&gt; postNode(String nodeId, byte[] content) {
  MultiValueMap&lt;String, Object&gt; bodyMap = new LinkedMultiValueMap&lt;&gt;();
ByteArrayResource contentsAsResource = new ByteArrayResource(content) {
    @Override
    public String getFilename() {
        return &quot;name22222&quot;;
    }
};

  bodyMap.add(&quot;filedata&quot;, contentsAsResource);

  ///bodyMap.add(&quot;filedata&quot;, content);// why this does not work??!

  HttpHeaders headers = new HttpHeaders();
  headers.setContentType(MediaType.MULTIPART_FORM_DATA);
  HttpEntity&lt;MultiValueMap&lt;String, Object&gt;&gt; requestEntity = new HttpEntity&lt;&gt;(bodyMap, headers);
        return restTemplate.exchange(&quot;/nodes/{nodeId}/children&quot;, HttpMethod.POST, requestEntity, byte[].class, nodeId);
}

but I have two questions:

1 - why the commented line does not work?

2 - the docs says :

> You can use the name field to give an alternative name for the new
> file.

I did not use a &quot;name&quot; field, but the server saved my files with the correct name(=&quot;name22222&quot;), why?(I thought multipart/form-data is a kind of a simple name-value, if this is correct then I have a field named "filedata" and its value is my byte array content, so how the file name is send?). and how can I specify the file name with a field?

update :
i think i found my answers. i just need to read about multipart/form-data!

答案1

得分: 5

也许这个示例对于了解如何使用Spring上传一个或多个文件会很有帮助。

     byte[] fileContent = "testFileContent".getBytes();
     String filename = "testFile.xml";

     MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
     ContentDisposition contentDisposition = ContentDisposition
         .builder("form-data")
         .name("file")
         .filename(filename)
         .build();

     fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
     HttpEntity<byte[]> fileEntity = new HttpEntity<>(fileContent, fileMap);

     MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
     body.add("file", fileEntity);

     HttpHeaders headers = new HttpHeaders();
     headers.setContentType(MediaType.MULTIPART_FORM_DATA);

     HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);

     ResponseEntity<String> response = restTemplate
         .postForEntity("/import/file", requestEntity, String.class);
英文:

Perhaps this example will be useful to find out how you can upload one or more files using Spring.

     
     byte[] fileContent = &quot;testFileContent&quot;.getBytes();
     String filename = &quot;testFile.xml&quot;;
 
     MultiValueMap&lt;String, String&gt; fileMap = new LinkedMultiValueMap&lt;&gt;();
     ContentDisposition contentDisposition = ContentDisposition
         .builder(&quot;form-data&quot;)
         .name(&quot;file&quot;)
         .filename(filename)
         .build();
 
     fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
     HttpEntity&lt;byte[]&gt; fileEntity = new HttpEntity&lt;&gt;(fileContent, fileMap);
 
     MultiValueMap&lt;String, Object&gt; body = new LinkedMultiValueMap&lt;&gt;();
     body.add(&quot;file&quot;, fileEntity);
 
     HttpHeaders headers = new HttpHeaders();
     headers.setContentType(MediaType.MULTIPART_FORM_DATA);

     HttpEntity&lt;MultiValueMap&lt;String, Object&gt;&gt; requestEntity = new HttpEntity&lt;&gt;(body, headers);
 
     ResponseEntity&lt;String&gt; response = restTemplate
         .postForEntity(&quot;/import/file, requestEntity, String.class);
      

huangapple
  • 本文由 发表于 2020年4月11日 04:05:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/61147883.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定