如何将多部分文件从另一个服务发送到一个服务

How to send a multipart file to a service from another service

我有两个端点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 工作得很好 fine.But 当我调用 /redirect 时它抛出一个错误

"exception": "org.springframework.http.converter.HttpMessageNotWritableException", "message": "Could not write JSON document: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])",

我不确定为什么要感谢 occuring.Any 帮助。

成功了

@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 并发送到服务。

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

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();
  }