使用 RestTemplate 请求将多部分文件作为 POST 参数发送

发布于 2024-09-30 20:44:59 字数 6365 浏览 3 评论 0原文

我正在使用 Spring 3 和 RestTemplate。我基本上有两个应用程序,其中一个必须将值发布到另一个应用程序。通过休息模板。

当要发布的值是字符串时,它工作得很好,但是当我必须发布混合和复杂的参数(如 MultipartFiles)时,我会收到转换器异常。

例如,我有这个:

App1 - PostController:

@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute UploadDTO pUploadDTO, 
        BindingResult pResult) throws URISyntaxException, IOException {
    URI uri = new URI("http://localhost:8080/app2/file/receiver");

    MultiValueMap<String, Object> mvm = new LinkedMultiValueMap<String, Object>();
    mvm.add("param1", "TestParameter");
    mvm.add("file", pUploadDTO.getFile()); // MultipartFile

    Map result = restTemplate.postForObject(uri, mvm, Map.class);
    return "redirect:postupload";
}

另一方面...我有另一个 Web 应用程序 (App2),它从 App1 接收参数。

App2 - ReceiverController

@RequestMapping(value = "/receiver", method = { RequestMethod.POST })
public String processUploadFile(
        @RequestParam(value = "param1") String param1,
        @RequestParam(value = "file") MultipartFile file) {

    if (file == null) {
        System.out.println("Shit!... is null");
    } else {
        System.out.println("Yes!... work done!");
    }
    return "redirect:postupload";
}

我的 application-context.xml:

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
        </list>
    </property>
</bean>

<bean id="multipartResolver"  
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
    <property name="maxUploadSize">  
        <value>104857600</value>  
    </property>  
    <property name="maxInMemorySize">  
        <value>4096</value>  
    </property>      
</bean>  

这是我在执行 RestTemplate 的 postForObject 时遇到的异常堆栈...

org.springframework.http.converter.HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.web.multipart.commons.CommonsMultipartFile]
at org.springframework.http.converter.FormHttpMessageConverter.writePart(FormHttpMessageConverter.java:292)
at org.springframework.http.converter.FormHttpMessageConverter.writeParts(FormHttpMessageConverter.java:252)
at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:242)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:194)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:1)
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:588)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:436)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:415)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:294)
at com.yoostar.admintool.web.UploadTestController.create(UploadTestController.java:86)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:421)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:409)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:774)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)

所以我的问题是:

  1. 是否可以发送 MultipartFile通过 RestTemplate 使用 POST?
  2. 我必须使用一些特定的转换器来发送此类对象吗?我的意思是我的配置中是否有一些 MultipartFileHttpMessageConverter 可以使用?

I am working with Spring 3 and RestTemplate. I have basically, two applications and one of them have to post values to the other app. through rest template.

When the values to post are Strings, it's work perfect, but when i have to post mixed and complex params (like MultipartFiles) i get an converter exception.

As example, i have this:

App1 - PostController:

@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute UploadDTO pUploadDTO, 
        BindingResult pResult) throws URISyntaxException, IOException {
    URI uri = new URI("http://localhost:8080/app2/file/receiver");

    MultiValueMap<String, Object> mvm = new LinkedMultiValueMap<String, Object>();
    mvm.add("param1", "TestParameter");
    mvm.add("file", pUploadDTO.getFile()); // MultipartFile

    Map result = restTemplate.postForObject(uri, mvm, Map.class);
    return "redirect:postupload";
}

On the other side... i have another web application (App2) that receives the parameters from the App1.

App2 - ReceiverController

@RequestMapping(value = "/receiver", method = { RequestMethod.POST })
public String processUploadFile(
        @RequestParam(value = "param1") String param1,
        @RequestParam(value = "file") MultipartFile file) {

    if (file == null) {
        System.out.println("Shit!... is null");
    } else {
        System.out.println("Yes!... work done!");
    }
    return "redirect:postupload";
}

My application-context.xml:

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
        </list>
    </property>
</bean>

<bean id="multipartResolver"  
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
    <property name="maxUploadSize">  
        <value>104857600</value>  
    </property>  
    <property name="maxInMemorySize">  
        <value>4096</value>  
    </property>      
</bean>  

Here is the stack of the exception that i am getting when i do the postForObject of the RestTemplate...

org.springframework.http.converter.HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.web.multipart.commons.CommonsMultipartFile]
at org.springframework.http.converter.FormHttpMessageConverter.writePart(FormHttpMessageConverter.java:292)
at org.springframework.http.converter.FormHttpMessageConverter.writeParts(FormHttpMessageConverter.java:252)
at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:242)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:194)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:1)
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:588)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:436)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:415)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:294)
at com.yoostar.admintool.web.UploadTestController.create(UploadTestController.java:86)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:421)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:409)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:774)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)

So my questions are:

  1. Is it possible to send MultipartFile through RestTemplate using POST?
  2. Are there some specific converters that I have to use to send this type of objects? I mean is there some MultipartFileHttpMessageConverter to use in my configuration?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

只是一片海 2024-10-07 20:44:59

解决此问题的一种方法是使用 ByteArrayResource,而无需使用需要磁盘上文件的 FileSystemResource,这样您就可以在帖子中发送字节数组(此代码适用于 Spring 3.2.3):

MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
final String filename="somefile.txt";
map.add("name", filename);
map.add("filename", filename);
ByteArrayResource contentsAsResource = new ByteArrayResource(content.getBytes("UTF-8")){
            @Override
            public String getFilename(){
                return filename;
            }
        };
map.add("file", contentsAsResource);
String result = restTemplate.postForObject(urlForFacade, map, String.class);

我重写 getFilename ByteArrayResource 的,因为如果我不这样做,我会得到一个空指针异常(显然这取决于java激活.jar是否在类路径上,如果是,它将使用文件名来尝试确定内容类型)

A way to solve this without needing to use a FileSystemResource that requires a file on disk, is to use a ByteArrayResource, that way you can send a byte array in your post (this code works with Spring 3.2.3):

MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
final String filename="somefile.txt";
map.add("name", filename);
map.add("filename", filename);
ByteArrayResource contentsAsResource = new ByteArrayResource(content.getBytes("UTF-8")){
            @Override
            public String getFilename(){
                return filename;
            }
        };
map.add("file", contentsAsResource);
String result = restTemplate.postForObject(urlForFacade, map, String.class);

I override the getFilename of the ByteArrayResource because if I don't I get a null pointer exception (apparently it depends on whether the java activation .jar is on the classpath, if it is, it will use the file name to try to determine the content type)

双手揣兜 2024-10-07 20:44:59

前几天我也遇到了同样的问题。谷歌搜索让我来到这里和其他几个地方,但没有一个给出这个问题的解决方案。我最终将上传的文件(MultiPartFile)保存为 tmp 文件,然后使用 FileSystemResource 通过 RestTemplate 上传它。这是我使用的代码,

String tempFileName = "/tmp/" + multiFile.getOriginalFileName();
FileOutputStream fo = new FileOutputStream(tempFileName);

fo.write(asset.getBytes());    
fo.close();   

parts.add("file", new FileSystemResource(tempFileName));    
String response = restTemplate.postForObject(uploadUrl, parts, String.class, authToken, path);   


//clean-up    
File f = new File(tempFileName);    
f.delete();

我仍在寻找更优雅的解决方案来解决这个问题。

I also ran into the same issue the other day. Google search got me here and several other places, but none gave the solution to this issue. I ended up saving the uploaded file (MultiPartFile) as a tmp file, then use FileSystemResource to upload it via RestTemplate. Here's the code I use,

String tempFileName = "/tmp/" + multiFile.getOriginalFileName();
FileOutputStream fo = new FileOutputStream(tempFileName);

fo.write(asset.getBytes());    
fo.close();   

parts.add("file", new FileSystemResource(tempFileName));    
String response = restTemplate.postForObject(uploadUrl, parts, String.class, authToken, path);   


//clean-up    
File f = new File(tempFileName);    
f.delete();

I am still looking for a more elegant solution to this problem.

世态炎凉 2024-10-07 20:44:59

我最近为这个问题苦苦挣扎了3天。客户端发送请求的方式可能不是原因,服务器可能未配置为处理多部分请求。这是我必须做的才能使其正常工作:

pom.xml - 添加了 commons-fileupload 依赖项(如果您不使用依赖项管理(例如 maven),则下载 jar 并将其添加到您的项目中)

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>${commons-version}</version>
</dependency>

web.xml - 添加多部分过滤器和映射

<filter>
  <filter-name>multipartFilter</filter-name>
  <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>multipartFilter</filter-name>
  <url-pattern>/springrest/*</url-pattern>
</filter-mapping>

app-context.xml - 添加多部分解析器

<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <beans:property name="maxUploadSize">
        <beans:value>10000000</beans:value>
    </beans:property>
</beans:bean>

您的控制器

@RequestMapping(value=Constants.REQUEST_MAPPING_ADD_IMAGE, method = RequestMethod.POST, produces = { "application/json"})
public @ResponseBody boolean saveStationImage(
        @RequestParam(value = Constants.MONGO_STATION_PROFILE_IMAGE_FILE) MultipartFile file,
        @RequestParam(value = Constants.MONGO_STATION_PROFILE_IMAGE_URI) String imageUri, 
        @RequestParam(value = Constants.MONGO_STATION_PROFILE_IMAGE_TYPE) String imageType, 
        @RequestParam(value = Constants.MONGO_FIELD_STATION_ID) String stationId) {
    // Do something with file
    // Return results
}

您的客户端

public static Boolean updateStationImage(StationImage stationImage) {
    if(stationImage == null) {
        Log.w(TAG + ":updateStationImage", "Station Image object is null, returning.");
        return null;
    }

    Log.d(TAG, "Uploading: " + stationImage.getImageUri());
    try {
        RestTemplate restTemplate = new RestTemplate();
        FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
        formConverter.setCharset(Charset.forName("UTF8"));
        restTemplate.getMessageConverters().add(formConverter);
        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAccept(Collections.singletonList(MediaType.parseMediaType("application/json")));

        MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();

        parts.add(Constants.STATION_PROFILE_IMAGE_FILE, new FileSystemResource(stationImage.getImageFile()));
        parts.add(Constants.STATION_PROFILE_IMAGE_URI, stationImage.getImageUri());
        parts.add(Constants.STATION_PROFILE_IMAGE_TYPE, stationImage.getImageType());
        parts.add(Constants.FIELD_STATION_ID, stationImage.getStationId());

        return restTemplate.postForObject(Constants.REST_CLIENT_URL_ADD_IMAGE, parts, Boolean.class);
    } catch (Exception e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));

        Log.e(TAG + ":addStationImage", sw.toString());
    }

    return false;
}

这应该可以解决问题。我添加了尽可能多的信息,因为我花了几天时间将整个问题的零碎内容拼凑在一起,我希望这会有所帮助。

I recently struggled with this issue for 3 days. How the client is sending the request might not be the cause, the server might not be configured to handle multipart requests. This is what I had to do to get it working:

pom.xml - Added commons-fileupload dependency (download and add the jar to your project if you are not using dependency management such as maven)

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>${commons-version}</version>
</dependency>

web.xml - Add multipart filter and mapping

<filter>
  <filter-name>multipartFilter</filter-name>
  <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>multipartFilter</filter-name>
  <url-pattern>/springrest/*</url-pattern>
</filter-mapping>

app-context.xml - Add multipart resolver

<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <beans:property name="maxUploadSize">
        <beans:value>10000000</beans:value>
    </beans:property>
</beans:bean>

Your Controller

@RequestMapping(value=Constants.REQUEST_MAPPING_ADD_IMAGE, method = RequestMethod.POST, produces = { "application/json"})
public @ResponseBody boolean saveStationImage(
        @RequestParam(value = Constants.MONGO_STATION_PROFILE_IMAGE_FILE) MultipartFile file,
        @RequestParam(value = Constants.MONGO_STATION_PROFILE_IMAGE_URI) String imageUri, 
        @RequestParam(value = Constants.MONGO_STATION_PROFILE_IMAGE_TYPE) String imageType, 
        @RequestParam(value = Constants.MONGO_FIELD_STATION_ID) String stationId) {
    // Do something with file
    // Return results
}

Your client

public static Boolean updateStationImage(StationImage stationImage) {
    if(stationImage == null) {
        Log.w(TAG + ":updateStationImage", "Station Image object is null, returning.");
        return null;
    }

    Log.d(TAG, "Uploading: " + stationImage.getImageUri());
    try {
        RestTemplate restTemplate = new RestTemplate();
        FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
        formConverter.setCharset(Charset.forName("UTF8"));
        restTemplate.getMessageConverters().add(formConverter);
        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAccept(Collections.singletonList(MediaType.parseMediaType("application/json")));

        MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();

        parts.add(Constants.STATION_PROFILE_IMAGE_FILE, new FileSystemResource(stationImage.getImageFile()));
        parts.add(Constants.STATION_PROFILE_IMAGE_URI, stationImage.getImageUri());
        parts.add(Constants.STATION_PROFILE_IMAGE_TYPE, stationImage.getImageType());
        parts.add(Constants.FIELD_STATION_ID, stationImage.getStationId());

        return restTemplate.postForObject(Constants.REST_CLIENT_URL_ADD_IMAGE, parts, Boolean.class);
    } catch (Exception e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));

        Log.e(TAG + ":addStationImage", sw.toString());
    }

    return false;
}

That should do the trick. I added as much information as possible because I spent days, piecing together bits and pieces of the full issue, I hope this will help.

栀子花开つ 2024-10-07 20:44:59
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("name 1", "value 1");
parts.add("name 2", "value 2+1");
parts.add("name 2", "value 2+2");
Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg");
parts.add("logo", logo);
Source xml = new StreamSource(new StringReader("<root><child/></root>"));
parts.add("xml", xml);

template.postForLocation("http://example.com/multipart", parts);
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("name 1", "value 1");
parts.add("name 2", "value 2+1");
parts.add("name 2", "value 2+2");
Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg");
parts.add("logo", logo);
Source xml = new StreamSource(new StringReader("<root><child/></root>"));
parts.add("xml", xml);

template.postForLocation("http://example.com/multipart", parts);
尾戒 2024-10-07 20:44:59

我们的一个人对文件系统资源做了类似的事情。
尝试

mvm.add("file", new FileSystemResource(pUploadDTO.getFile())); 

假设您的 .getFile 的输出是一个 java File 对象,它应该与我们的一样工作,其中
只有一个 File 参数。

One of our guys does something similar with the filesystemresource.
try

mvm.add("file", new FileSystemResource(pUploadDTO.getFile())); 

assuming the output of your .getFile is a java File object, that should work the same as ours, which
just has a File parameter.

够运 2024-10-07 20:44:59

您可以简单地使用 MultipartHttpServletRequest

示例:

 @RequestMapping(value={"/upload"}, method = RequestMethod.POST,produces = "text/html; charset=utf-8")
 @ResponseBody
 public String upload(MultipartHttpServletRequest request /*@RequestBody MultipartFile file*/){
    String responseMessage = "OK";
    MultipartFile file = request.getFile("file");
    String param = request.getParameter("param");
    try {
        System.out.println(file.getOriginalFilename());
        System.out.println("some param = "+param);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8));
        // read file
    }
    catch(Exception ex){
        ex.printStackTrace();
        responseMessage = "fail";
    }
     return responseMessage;
}

其中 request.getParameter() 中的参数名称必须与相应的前端名称相同。

请注意,该文件是通过 getFile() 提取的,而其他附加参数是通过 getParameter() 提取的

You may simply use MultipartHttpServletRequest

Example:

 @RequestMapping(value={"/upload"}, method = RequestMethod.POST,produces = "text/html; charset=utf-8")
 @ResponseBody
 public String upload(MultipartHttpServletRequest request /*@RequestBody MultipartFile file*/){
    String responseMessage = "OK";
    MultipartFile file = request.getFile("file");
    String param = request.getParameter("param");
    try {
        System.out.println(file.getOriginalFilename());
        System.out.println("some param = "+param);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8));
        // read file
    }
    catch(Exception ex){
        ex.printStackTrace();
        responseMessage = "fail";
    }
     return responseMessage;
}

Where parameters names in request.getParameter() must be same with corresponding frontend names.

Note, that file extracted via getFile() while other additional parameters extracted via getParameter()

凉宸 2024-10-07 20:44:59

我必须做@Luxspes 上面做的同样的事情..并且我正在使用 Spring 4.2.6。花了相当多的时间弄清楚为什么 ByteArrayResource 从客户端传输到服务器,但服务器无法识别它。

ByteArrayResource contentsAsResource = new ByteArrayResource(byteArr){
            @Override
            public String getFilename(){
                return filename;
            }
        };

I had to do the same thing that @Luxspes did above..and I am using Spring 4.2.6. Spent quite some time figuring why is ByteArrayResource getting transferred from client to server, but the server is not recognizing it.

ByteArrayResource contentsAsResource = new ByteArrayResource(byteArr){
            @Override
            public String getFilename(){
                return filename;
            }
        };
青衫负雪 2024-10-07 20:44:59

如果您必须发送一个由需要使用特定 HttpMessageConverter 进行转换的对象组成的多部分文件,并且无论您尝试什么,您都会收到“没有合适的 HttpMessageConverter”错误,您可能需要尝试使用这:

RestTemplate restTemplate = new RestTemplate();
FormHttpMessageConverter converter = new FormHttpMessageConverter();

converter.addPartConverter(new TheRequiredHttpMessageConverter());
//for example, in my case it was "new MappingJackson2HttpMessageConverter()"

restTemplate.getMessageConverters().add(converter);

这通过一个自定义对象解决了我的问题,该对象与文件(在我的例子中是 FileSystemResource 的实例)一起,是我需要发送的多部分文件的一部分。
我尝试使用 TrueGuidance 的解决方案(以及在网络上找到的许多其他解决方案)无济于事,然后我查看了 FormHttpMessageConverter 的源代码代码并尝试了这个。

If you have to send a multipart file that is composed, among other things, by an Object that needs to be converted with a specific HttpMessageConverter and you get the "no suitable HttpMessageConverter" error no matter what you try, you may want to try with this:

RestTemplate restTemplate = new RestTemplate();
FormHttpMessageConverter converter = new FormHttpMessageConverter();

converter.addPartConverter(new TheRequiredHttpMessageConverter());
//for example, in my case it was "new MappingJackson2HttpMessageConverter()"

restTemplate.getMessageConverters().add(converter);

This solved the problem for me with a custom Object that, together with a file (instanceof FileSystemResource, in my case), was part of the multipart file I needed to send.
I tried with TrueGuidance's solution (and many others found around the web) to no avail, then I looked at FormHttpMessageConverter's source code and tried this.

感悟人生的甜 2024-10-07 20:44:59

您必须将 FormHttpMessageConverter 添加到 applicationContext.xml 才能发布多部分文件。

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
        </list>
    </property>
</bean>

请参阅 http:// docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/FormHttpMessageConverter.html 例如。

You have to add the FormHttpMessageConverter to your applicationContext.xml to be able to post multipart files.

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
        </list>
    </property>
</bean>

See http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/FormHttpMessageConverter.html for examples.

那小子欠揍 2024-10-07 20:44:59

我遇到了这个问题,并找到了比使用 ByteArrayResource 更简单的解决方案。

只需执行

public void loadInvoices(MultipartFile invoices, String channel) throws IOException {

    init();

    Resource invoicesResource = invoices.getResource();

    LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
    parts.add("file", invoicesResource);

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
    httpHeaders.set("channel", channel);

    HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);

    String url = String.format("%s/rest/inbound/invoices/upload", baseUrl);

    restTemplate.postForEntity(url, httpEntity, JobData.class);
}

即可,无需搞乱文件系统或字节数组。

I had this issue and found a much simpler solution than using a ByteArrayResource.

Simply do

public void loadInvoices(MultipartFile invoices, String channel) throws IOException {

    init();

    Resource invoicesResource = invoices.getResource();

    LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
    parts.add("file", invoicesResource);

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
    httpHeaders.set("channel", channel);

    HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);

    String url = String.format("%s/rest/inbound/invoices/upload", baseUrl);

    restTemplate.postForEntity(url, httpEntity, JobData.class);
}

It works, and no messing around with the file system or byte arrays.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文