Saltar al contenido

Cómo enviar datos de formulario de varias partes con restTemplate Spring-mvc

Presta atención porque en esta sección hallarás la solución que buscas.Este escrito ha sido aprobado por nuestros expertos para asegurar la calidad y exactitud de nuestro post.

Solución:

Lectura de todo el archivo en un ByteArrayResource puede ser un problema de consumo de memoria con archivos grandes.

Puede cargar un archivo proxy en un controlador spring mvc usando un InputStreamResource:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResponseEntity uploadImages(@RequestPart("images") final MultipartFile[] files) throws IOException 
    LinkedMultiValueMap map = new LinkedMultiValueMap<>();
    String response;
    HttpStatus httpStatus = HttpStatus.CREATED;

    try 
        for (MultipartFile file : files) 
            if (!file.isEmpty()) 
                map.add("images", new MultipartInputStreamFileResource(file.getInputStream(), file.getOriginalFilename()));
            
        

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        String url = "http://example.com/upload";

        HttpEntity> requestEntity = new HttpEntity<>(map, headers);
        response = restTemplate.postForObject(url, requestEntity, String.class);

     catch (HttpStatusCodeException e) 
        httpStatus = HttpStatus.valueOf(e.getStatusCode().value());
        response = e.getResponseBodyAsString();
     catch (Exception e) 
        httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
        response = e.getMessage();
    

    return new ResponseEntity<>(response, httpStatus);


class MultipartInputStreamFileResource extends InputStreamResource 

    private final String filename;

    MultipartInputStreamFileResource(InputStream inputStream, String filename) 
        super(inputStream);
        this.filename = filename;
    

    @Override
    public String getFilename() 
        return this.filename;
    

    @Override
    public long contentLength() throws IOException 
        return -1; // we do not want to generally read the whole stream into memory ...
    

Obtiene la excepción porque ninguno de los MessageConverters predeterminados de RestTemplate sabe cómo serializar el InputStream contenido en el archivo MultipartFile. Al enviar objetos a través de RestTemplate, en la mayoría de los casos desea enviar POJO. Puede solucionar esto agregando los bytes de MultipartFile a MultiValueMap en lugar del propio MultipartFile.

Creo que también hay algo mal con su parte de servlet. Por ejemplo

File file1 = (File) req.getAttribute("userfile1");

siempre debe volver nullya que el método getAttribute de ServletRequest no devuelve parámetros de solicitud/formulario, pero attributes establecido por el contexto del servlet. ¿Está seguro de que realmente está funcionando con su ejemplo de curl?

Aquí hay un ejemplo de un método Spring MVC que reenvía un archivo a un servlet:

Servlet (aunque lo probé ejecutándose en un contenedor Spring MVC), adaptado de aquí:

@RequestMapping("/pi")
private void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException 

  final String path = request.getParameter("destination");
  final Part filePart = request.getPart("file");
  final String fileName = request.getParameter("filename");

  OutputStream out = null;
  InputStream fileContent = null;
  final PrintWriter writer = response.getWriter();

  try 
    out = new FileOutputStream(new File(path + File.separator
            + fileName));
    fileContent = filePart.getInputStream();

    int read = 0;
    final byte[] bytes = new byte[1024];

    while ((read = fileContent.read(bytes)) != -1) 
      out.write(bytes, 0, read);
    
    writer.println("New file " + fileName + " created at " + path);

   catch (FileNotFoundException fne) 
    writer.println("You either did not specify a file to upload or are "
            + "trying to upload a file to a protected or nonexistent "
            + "location.");
    writer.println("
ERROR: " + fne.getMessage()); finally if (out != null) out.close(); if (fileContent != null) fileContent.close(); if (writer != null) writer.close();

Método Spring MVC:

@ResponseBody
@RequestMapping(value="/upload/", method=RequestMethod.POST, 
        produces = "text/plain")
public String uploadFile(MultipartHttpServletRequest request) 
        throws IOException 

  Iterator itr = request.getFileNames();

  MultipartFile file = request.getFile(itr.next());
  MultiValueMap parts = 
          new LinkedMultiValueMap();
  parts.add("file", new ByteArrayResource(file.getBytes()));
  parts.add("filename", file.getOriginalFilename());

  RestTemplate restTemplate = new RestTemplate();
  HttpHeaders headers = new HttpHeaders();
  headers.setContentType(MediaType.MULTIPART_FORM_DATA);

  HttpEntity> requestEntity =
          new HttpEntity>(parts, headers);

  // file upload path on destination server
  parts.add("destination", "./");

  ResponseEntity response =
          restTemplate.exchange("http://localhost:8080/pi", 
                  HttpMethod.POST, requestEntity, String.class);

  if (response != null && !response.getBody().trim().equals("")) 
    return response.getBody();
  

  return "error";

Usando estos, puedo cargar con éxito un archivo a través del método MVC al servlet mediante el siguiente curl:

curl --form [email protected] localhost:8080/upload/

Desde la versión 5.1, Spring Framework se envía con su propio Resource implementación para MultipartFiles. Por lo tanto, puede simplificar la respuesta de Lorenzo eliminando el MultipartInputStreamFileResource class y llenando el mapa de la siguiente manera:

[...]

for (MultipartFile file : files) 
    if (!file.isEmpty()) 
        map.add("images", file.getResource());
    


[...]

Eres capaz de auxiliar nuestra tarea añadiendo un comentario y dejando una puntuación te estamos agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *