Skip to content
This repository was archived by the owner on Dec 31, 2024. It is now read-only.

How can i upload multi file. #68

Closed
JokerSun opened this issue Mar 29, 2019 · 6 comments
Closed

How can i upload multi file. #68

JokerSun opened this issue Mar 29, 2019 · 6 comments

Comments

@JokerSun
Copy link

JokerSun commented Mar 29, 2019

In my case , i want to upload multi file ,but i get exception java.lang.IllegalStateException: Method has too many Body parameters,my code like that

@FeignClient(configuration = MultipartFormDataConfig.class)
public class Demo{
	@PostMapping(
		path = "/upload",
		consumes = org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE
	)
	Response uploadFile(
		@RequestPart MultipartFile file1,
		@RequestPart MultipartFile file2
	);
}
@JokerSun JokerSun changed the title How can i upload multi file。 How can i upload multi file. Mar 29, 2019
@xxlabaza
Copy link
Collaborator

@JokerSun the feature was broken, but I've already fixed it in the new version 3.8.0

Take a look at those client examples 1 and 2. There is an example of the server side

Your sample with several MultipartFile argument doesn't work, because of Spring's contract implementation and it throws an exception like IllegalStateException: Method has too many Body parameters in such cases.

@JokerSun
Copy link
Author

JokerSun commented Apr 4, 2019

@xxlabaza Thanks for your supporting, i got the example and my question isn't just that , according to the protocol of multipart-form/data carrying either named parameters in request body is allowed, so how can i construct a interface like that

@PostMapping(
		path = "/upload",
		consumes = org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE
)
Response uploadFile(
		@RequestParam String parameter1,
		@RequestPart String parameter2,
		@ReuqestPart String json,
		@RequestPart MultipartFile file1,
		@RequestPart MultipartFile file2
);

then i hope it will be send like that

POST /upload?parameter1=**** HTTP/1.1
*** headers ***
------FormBoundary
Content-Disposition: form-data; name="parameter2"

value
------FormBoundary
Content-Disposition: form-data; name="json"
Content-Type: application/json

value
------FormBoundary
Content-Disposition: form-data; name="image"; filename="file1"
Content-Type: application/octet-stream

value
------FormBoundary
Content-Disposition: form-data; name="image"; filename="file2"
Content-Type: application/octet-stream

value
------FormBoundary--

Is there a solution?

@jianguyuxing
Copy link

jianguyuxing commented Apr 8, 2019

不需要重写Contract啊。但是feign默认使用的是SpringMVC 的Contract。
一、需要声明使用feign的自带Contract,不让它使用SpringMvcContract。
第二点,需要使用我提到的那个encoder。
三、接口的请求形式不是你写的这样,我写成这样是在生产者端接收用的。在FeignClient端用的注解不是这样的,FeignClient客户端的请求路径用的是@RequestLine注解和@ Param注解,只有生产者端才使用@PostMapping和@RequestPart注解。你可以认真看下我给的例子。这里给你个博客地址吧。https://blog.csdn.net/qq_34523427/article/details/88863800

@JokerSun
Copy link
Author

JokerSun commented Apr 8, 2019

@jianguyuxing 谢谢您在百忙之中抽空回复,我知道我的写法现有的contract不支持,但是我是希望实现这种需求,因为这样的写法能够更好的表达这个接口的行为,并且能够跟spring mvc的写法保持一致。您的例子我看了,确实可以实现功能,但是使用的是feign的原生注解,这样就和我们公司现有的代码风格产生冲突。我会抽时间把我的想法实现出来,然后再与您交流。

@xxlabaza
Copy link
Collaborator

Так, на сколько я вижу вы тут сами уже во всём разобрались...

@rojekabc
Copy link

rojekabc commented Nov 3, 2020

Ok. I see, that this issue is closed, but I'll describe here a little workaround. I hope this will help someone. I resolve this in the issue, when I's trying to send something like this via feign client:

void upload(
   @RequestPart(name="main") MultipartFile mainFile,
   @RequestPart(name="attachments") MultipartFile[] attachments);

In case of two request parts, when tries create feign client instance Method has too many Body parameters occurs.
If I change them to RequestParam, than I get nothing (null).

So I do this in such way, that I create two interface API.
The first version, with two RequestPart, is used on side of Controller implementation - in such way it recognizes correctly incoming parts and puts as argues.
The second version, used to create feign client, looks like this

void upload(@RequestPart MultipartFile[] documents);

I'm using this with feign client configuration

    @Configuration
    class MultipartSupportConfig {

        @Bean
        public Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
            return new SpringFormEncoder(new SpringEncoder(messageConverters));
        }
    }

and with fix from PR: #97 - it's needed, if for one field name (here attachments) we'd like send more than one multipart-file.

Then, if we'd like to use upload via feign client, we should call upload and create named multiparts.
In this example example:

MultipartFile[] documents = new MultipartFile[3];
documents[0] = new MockMultipartFile("main", "sample-file.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, "MAIN-FILE-CONTENT".getBytes());
documents[1] = new MockMultipartFile("attachments", "attach-1.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, "ONE-CONTENT".getBytes());
documents[2] = new MockMultipartFile("attachments", "attach-2.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, "TWO-CONTENT".getBytes());
FeignClientInstance.upload(documents);

In this way multi part files names are used as field names. This will be recognized by controller and assigned to dedicated argues.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants