【问题标题】:How to send a multipart file to a service from another service如何将多部分文件从另一个服务发送到服务
【发布时间】:2018-04-15 16:04:57
【问题描述】:

我有两个端点 api,它们是 /upload/redirect

/upload 是我直接上传文件的地方。 /redirect 是我接收文件并将其传递给上传并从 /upload 获取 JSON 响应的位置。所以下面是我的代码:

package com.example;

import java.io.BufferedOutputStream;

import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class UserLogsController {

    @Autowired
    @Qualifier("restTemplateUserRegitration")
    private RestTemplate restTemplateUserRegitration;

    @Bean
    public RestTemplate restTemplateUserRegitration() {

        RestTemplateBuilder builderUserRegitration = new RestTemplateBuilder();
        RestTemplate buildUserRegitration = builderUserRegitration.build();

        return buildUserRegitration;
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public @ResponseBody ResponseEntity<Map<String, Object>> handleFileUpload(
            @RequestParam("file") MultipartFile file) {
        String name = file.getName();
        System.out.println(name);
        if (!file.isEmpty()) {
            try {
                byte[] bytes = file.getBytes();
                BufferedOutputStream stream = new BufferedOutputStream(
                        new FileOutputStream(new File("D:\\myfile.csv")));
                stream.write(bytes);
                stream.close();

                JwtAuthenticationErrorResponse FeedBackResponse = new JwtAuthenticationErrorResponse();
                FeedBackResponse.setCode(100);
                FeedBackResponse.setMessage("Successfully Updated Batch User List");
                Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
                FeedBackStatus.put("status", FeedBackResponse);
                return ResponseEntity.ok(FeedBackStatus);

            } catch (Exception e) {
                JwtAuthenticationErrorResponse FeedBackResponse = new JwtAuthenticationErrorResponse();
                FeedBackResponse.setCode(100);
                FeedBackResponse.setMessage(e.getMessage());
                Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
                FeedBackStatus.put("status", FeedBackResponse);
                return ResponseEntity.ok(FeedBackStatus);
            }
        } else {
            JwtAuthenticationErrorResponse FeedBackResponse = new JwtAuthenticationErrorResponse();
            FeedBackResponse.setCode(100);
            FeedBackResponse.setMessage("Successfully Updated Batch User List");
            Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
            FeedBackStatus.put("status", FeedBackResponse);
            return ResponseEntity.ok(FeedBackStatus);
        }
    }

    @RequestMapping(value = "/redirect", produces = { MediaType.APPLICATION_JSON_VALUE }, method = RequestMethod.POST)
    public ResponseEntity<?> registerBatchUser(@RequestParam("file") MultipartFile file) {

        Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
        FeedBackStatus = restTemplateUserRegitration.postForObject("http://localhost:8080/upload", file, Map.class);
        return ResponseEntity.ok(FeedBackStatus);

    }

}

端点 /upload 工作得很好。但是当我调用 /redirect 时,它会抛出一个错误

“异常”: "org.springframework.http.converter.HttpMessageNotWritableException", “消息”:“无法写入 JSON 文档:找不到序列化程序 类 java.io.FileDescriptor 并且没有发现要创建的属性 BeanSerializer(为避免异常,禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过引用链: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"]); 嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:没有序列化程序 找到类 java.io.FileDescriptor 并且没有发现任何属性 创建 BeanSerializer(为避免异常,禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过引用链: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])",

我不确定为什么会发生这种情况。感谢任何帮助。

【问题讨论】:

    标签: java spring-boot multipartform-data resttemplate


    【解决方案1】:

    这就是诀窍

    @RequestMapping(value = "/redirect", produces = { MediaType.APPLICATION_JSON_VALUE }, method = RequestMethod.POST)
        public ResponseEntity<?> registerBatchUser(@RequestParam("file") MultipartFile file) {
           if (!file.isEmpty()) {
                try {
                    byte[] bytes = file.getBytes();
                    BufferedOutputStream stream = new BufferedOutputStream(
                            new FileOutputStream(new File("D:\\myfileredirect.csv")));
                    stream.write(bytes);
                    stream.close();
    
    
                } catch (Exception e) {
                    JwtAuthenticationErrorResponse FeedBackResponse = new JwtAuthenticationErrorResponse();
                    FeedBackResponse.setCode(100);
                    FeedBackResponse.setMessage(e.getMessage());
                    Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
                    FeedBackStatus.put("status", FeedBackResponse);
                    return ResponseEntity.ok(FeedBackStatus);
                }
            MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>();
            parameters.add("file", new FileSystemResource("D:\\myfileredirect.csv")); 
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "multipart/form-data");
    
    
    
            Map<String, Object> FeedBackStatus=new HashMap<String, Object>();
            FeedBackStatus =  restTemplateUserRegitration.exchange("http://localhost:8080/upload",  HttpMethod.POST,  new HttpEntity<MultiValueMap<String, Object>>(parameters, headers), Map.class).getBody();
            return ResponseEntity.ok(FeedBackStatus);
    
        }
    

    所以我所做的基本上是收集文件重写它,然后转换为 MultiValueMap 并发送到服务。

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,我使用的是临时文件而不是文件。

      Path tempFile = Files.createTempFile(null, null);
        
      Files.write(tempFile, multipartFile.getBytes());
      File fileToSend = tempFile.toFile();
      
      MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
            
      parameters.add("file", new FileSystemResource(fileToSend));
      
      HttpHeaders headers = new HttpHeaders();
      headers.set("Content-Type", "multipart/form-data");
      
      HttpEntity httpEntity = new HttpEntity<>(parameters, headers);
      
      try {
          restTemplate.exchange(apiUrl, HttpMethod.POST,
                          httpEntity, MyClazz.class);
        } finally {
          fileAEnviar.delete();
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-14
        • 2019-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多