Fork me on GitHub
余鸢

File Upload

上传单个文件

通过HTTP Post接收上传的文件,您需要执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping(
value = "...",
method = RequestMethod.POST,
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
public Object uploadFile(@RequestPart MultipartFile file) {
String fileName = file.getOriginalFilename();
InputStream inputStream = file.getInputStream();
String contentType = file.getContentType();
.
.
.
}

请注意,@RequestPart参数的名称需要与请求中的part的名称匹配。

HTML:

1
2
3
<form action="/..." enctype="multipart/form-data" method="post">
<input type="file" name="file">
</form>

HTML(Spring TagLibs):

1
2
3
<form action="/..." enctype="multipart/form-data" method="post">
<form:input type="file" path="file">
</form>

作为原始HTTP请求:

1
2
3
4
5
6
7
8
9
10
POST /... HTTP/1.1
Host: ...
Content-Type: multipart/form-data; boundary=----------287032381131322
------------287032381131322
Content-Disposition: form-data; name="file"; filename="r.gif"
Content-Type: image/gif
GIF87a.............,...........D..;
------------287032381131322--

该请求表示为:

1
2
fileName == "r.gif"
contentType == "image/gif"

将part编组为对象

如果你想将一个部分的内容转换为域对象(例如UserAccountAddress),那么过程很简单:

可以上传多个parts,每个part使用不同的名称。 对于每个part名称,需要使用@RequestPart注释的一个参数,其name与part名称匹配。

要接收通过HTTP Post上传的文件,您需要执行以下操作:

1
2
3
4
5
6
7
8
9
10
@RequestMapping(
value = "...",
method = RequestMethod.POST,
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
public Object uploadFile(@RequestPart Address address,) {
.
.
.
}

原始HTTP请求:

1
2
3
4
5
6
7
8
9
10
POST /... HTTP/1.1
Host: ...
Content-Type: multipart/form-data; boundary=----------287032381131322
------------287032381131322
Content-Disposition: form-data; name="address"; filename="address.json"
Content-Type: application/json
{"houseNumber": "10/A", "streetName": "Dumbldore Road", "town": "Hogsmede"}
------------287032381131322--

最重要的事情是:

  • part的名称必须与变量的名称匹配。
  • 如果已将其作为常规请求发送,则part的Content-Type必须是Spring能够处理的内容类型。 也就是说,如果可以对具有foo/barContent-Type的端点执行POST,并且Spring能够将其转换为对象,那么它也能够将part编组到对象中。
  • 你必须能够设置part的Content-Type。 如果不能,这种方法将不工作 - Spring不会尝试猜测的部分的Content-Type

上传多个文件

通过单个HTTP Post接收上传的多个文件,您需要执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping(
value = "...",
method = RequestMethod.POST,
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
public Object uploadFile(@RequestPart MultipartFile[] files) {
for (file : files) {
String fileName = file.getOriginalFilename();
InputStream inputStream = file.getInputStream();
String contentType = file.getContentType();
.
.
.
}
}

请注意,@RequestPart参数的名称需要与请求中的part的名称匹配。

HTML:

1
2
3
4
<form action="/..." enctype="multipart/form-data" method="post">
<input type="file" name="files">
<input type="file" name="files">
</form>

原始HTTP请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /... HTTP/1.1
Host: ...
Content-Type: multipart/form-data; boundary=----------287032381131322
------------287032381131322
Content-Disposition: form-data; name="files"; filename="r.gif"
Content-Type: image/gif
GIF87a.............,...........D..;
------------287032381131322
Content-Disposition: form-data; name="files"; filename="banana.jpeg"
Content-Type: image/jpeg
GIF87a.............,...........D..;
------------287032381131322--

该请求表示为:

1
2
3
4
files[0].getOriginalFilename() == "r.gif"
files[0].getContentType() == "image/gif"
files[1].getOriginalFilename() == "r.jpeg"
files[1].getContentType() == "image/jpeg"

Syntax

@RequestPart(String, String, boolean)

参数 细节
@RequestPart 此注释指定参数应映射到给定的请求部分。 part名称必须与方法参数的名称匹配,除非你选择将其作为@RequestPart的参数提供。 如果part名称不能表示为Java名称(例如123),则可以使用@RequestPart的value属性指定实际名称。 例如 @RequestPart(“123”)String _123

如果你运行的是较早版本的Java(1.7之前版本),或者正在编译没有调试信息,那么Java将用arg0arg1等替换参数的名称,这将阻止Spring与它们匹配 part名称。 如果是这种情况,那么你将需要在@RequestPart注释中设置部件的名称,如参数中所述。