Erro 413 com arquivos acima de 1 MB - resolvido

29 respostas Resolvido
spring-bootspring
guilhermebhte

spring.servlet.multipart.max-file-size=128MB
spring.servlet.multipart.max-request-size=128MB
spring.servlet.multipart.enabled=true

e assim

spring.http.multipart.max-file-size = 20MB
spring.http.multipart.max-request-size = 20MB

O que está de errado ?

Access to XMLHttpRequest at ‘https://crud.movimentoneem.life/crud-api/api/carrousel/’ from origin ‘https://app.movimentoneem.life’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
polyfills-es2015.d868f9f91e9b61395ae1.js:1 POST https://crud.movimentoneem.life/crud-api/api/carrousel/ net::ERR_FAILED 413

Este erro da no console

29 Respostas

guilhermebhte

Alguém já passou por isso ?

É configuração do Spring que está errada ?

Configuração no servidor ?

Lucas_Camara

O content-type da requisição é multipart/form-data?

guilhermebhte

Testei com um assim:

<form
  [formGroup]="formGroup"
  fxLayout="column"
  fxLayoutGap="8px"
  style="padding: 0px 16px; margin-top: 20px"
  (ngSubmit)="salvar()"
>

e assim:

<form
  [formGroup]="formGroup"
  fxLayout="column"
  fxLayoutGap="8px"
  style="padding: 0px 16px; margin-top: 20px"
  (ngSubmit)="salvar()"
  enctype="multipart/form-data"
>

Os dois deram o mesmo erro.

Lucas_Camara

Como está sendo feita a requisição na função salvar()?

guilhermebhte

Angular

async salvar(): Promise<void> {
  let httpReturn: any;
  
  try {
    const dto = "dto";
    const filesMultipartFormParam = "file";
    const formData: FormData = new FormData();
    const blob: Blob = new Blob([JSON.stringify(this.entidade)], {
      type: "application/json",
    });
    
    formData.append(dto, blob);
    
    if (this.arquivos !== undefined && this.arquivos !== null) {
      for (let i = 0; i < this.arquivos.length; i++) {
        formData.append(filesMultipartFormParam, this.arquivos[i]);
      }
    }
    
    if (this.formGroup.value.idString) {
      httpReturn = await this.http.put(
        this.environmentBackend + API + this.urlBase + "/" + this.formGroup.value.idString + "/",
        formData
      ).toPromise();
    } else {
      httpReturn = await this.http.post(
        this.environmentBackend + API + this.urlBase + "/", formData
      ).toPromise();
    }
    
    this.toastrService.success(httpReturn["texto"]);
    this.voltar();
  } catch (error: any) {
    this.erroSalvar = true;
    this.errorServiceS.error(error);
  }
}

Java

@ApiOperation("Cadastrar produto")
@PostMapping(consumes = MULTIPART_FORM_DATA_VALUE, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<?> inserir(
  @Valid @RequestPart final ProdutoFormDTO dto, 
  final MultipartFile file, 
  @ApiIgnore final Principal principal
) {
  try {
    service.salvar(dto, null, principal, file);
    return mensagemSalvar();
  } catch (final GeralException e) {
    return erroExceptionComRegra(e, ENTIDADE);
  } catch (final Exception e) {
    return excecaoGeralSalvar(e, ERROR, ENTIDADE, ENTIDADE);
  }
}
Lucas_Camara

Ah rapaiz, e esse erro de CORS? Será que ele tah impedindo algum header que permita o upload funcionar? (é soh um palpite).

guilhermebhte

O estranho que imagens abaixo de 1mega, passa.

Se for no cors o que pode ser ?

Lucas_Camara

Vc tem razão.


Quando a requisição é enviada, no console do navegador (na aba network), a requisição é realmente enviada como multipart/form-data?

guilhermebhte

Sim

guilhermebhte

image

guilhermebhte

Cors do java

package br.com.ghnetsoft.gestaovendasatendimento.crud.config;

import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Order(HIGHEST_PRECEDENCE)
@Slf4j
@Component
public class SmpleCORSFilter implements Filter {

    @Value("${origens-permitidas}")
    private String[] origensPermitidas;

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        log.info("Sistema de crud | SmpleCORSFilter inicio");
    }

    @Override
    public void doFilter(final ServletRequest req, final ServletResponse resp, final FilterChain chain) throws IOException, ServletException {
        log.info("doFilter");
        final HttpServletResponse response = (HttpServletResponse) resp;
        final HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
        response.setHeader("Access-Control-Expose-Headers", "Location");
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, response);
        }
    }

    @Override
    public void destroy() {
        //
    }
}
Lucas_Camara

Posta o application.yml ai (a parte onde vc tentou setar as propriedades referentes ao tamanho da requisição e multipart).

guilhermebhte
###### MULTIPART ######
spring.servlet.multipart.max-file-size=128MB
spring.servlet.multipart.max-request-size=128MB
guilhermebhte

Estranho, que parece estar certo, mas não está né

Pode ser algo no servidor se sim, o que pode ser ?

Porque em homologação funciona.

Lucas_Camara

Em outro ambiente funciona com arquivos acima de 1MB então?

Estava dando uma lida aqui para ver se encontrava algo, mas parece que está certo sua configuração. Vc usa o tomcat para subir o projeto? E qual a versão do spring-boot?

guilhermebhte

No ambiente de homologação funciona.

spring-2.3.5.RELEASE

start.sh está assim

#!/bin/bash

PORT="8080"
LOG_FILE="/var/log/gestaovendas.log"
JAR="/usr/local/gestaovendas/gestaovendasatendimentocrud.jar"

java -jar -Dserver.port=$PORT -Dspring.profiles.active=prod $JAR >> $LOG_FILE

De homolgação está assim

FROM adoptopenjdk/openjdk11:jre-11.0.9_11.1-alpine
VOLUME [ "/tmp" ]

RUN apk add --no-cache tzdata
ENV TZ America/Sao_Paulo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

COPY *.jar app.jar

ENTRYPOINT ["sh", "-c", "exec java -jar app.jar  -Dfile.encoding=UTF-8 --spring.profiles.active=hom"]
Lucas_Camara

Eita, então esse erro soh acontece no ambiente de produção? Quando vc roda local, funciona?

guilhermebhte

Local e ambiente de homologação funcionam

Lucas_Camara

Acho que tu pode colocar um log no endpoint que imprima todos os headers da requisição que estão chegando. E também investigar se realmente as propriedades de multipart que aumentam o limite do upload estão realmente sendo aplicadas em produção (tu consegue imprimir elas no log usando o @Value).

guilhermebhte

Como consigo imprimir estes logs ?

A requisição não chega nem no endpoint, entendo que o cors não deixa.

guilhermebhte

Pelo que entendi as configurações para o spring 2.3.5, deve ser estas, no properties

spring.servlet.multipart.max-file-size=128MB
spring.servlet.multipart.max-request-size=128MB
Lucas_Camara

Isso mesmo.

guilhermebhte

Fiz isto e

@Override
    public void doFilter(final ServletRequest req, final ServletResponse resp, final FilterChain chain) throws IOException, ServletException {
        final HttpServletResponse response = (HttpServletResponse) resp;
        final HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
        response.setHeader("Access-Control-Expose-Headers", "Location");
        for (final Enumeration<?> e = request.getHeaderNames(); e.hasMoreElements();) {
            final String nextHeaderName = (String) e.nextElement();
            final String headerValue = request.getHeader(nextHeaderName);
            log.info("nextHeaderName: " + nextHeaderName);
            log.info("headerValue: " + headerValue);
        }
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, response);
        }
    }

no log apareceu isto:

2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: x-forwarded-for
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: 191.185.125.215
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: host
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: xxxxxx
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: connection
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: close
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: content-length
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: [telefone removido]-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: sec-ch-ua
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: accept
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: application/json, text/plain, */*
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: content-type
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: multipart/form-data; boundary=----WebKitFormBoundaryBG5jKKXk4qGIDqYQ
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: authorization
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: bearer 9e02166b-5c74-45ec-83be-9b4004029f75
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: sec-ch-ua-mobile
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: ?0
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: user-agent
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: sec-ch-ua-platform
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: "Windows"
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: origin
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: 
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: sec-fetch-site
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: same-site
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: sec-fetch-mode
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: cors
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: sec-fetch-dest
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: empty
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: referer
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: https://app.movimentoneem.life/
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: accept-encoding
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: gzip, deflate, br
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				nextHeaderName: accept-language
2021-12-13 09:38:37 [http-nio-9103-exec-1] INFO  - b.c.g.g.crud.config.SmpleCORSFilter -
				headerValue: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,fr;q=0.6
guilhermebhte

Quando o arquivo é maior que 1 Mega, não chega no servidor nem no cors, poir não imprimi log

guilhermebhte

spring.servlet.multipart.max-file-size = 1MB # Tamanho máximo do arquivo. Os valores podem usar os sufixos “MB” ou “KB” para indicar megabytes ou kilobytes, respectivamente.

spring.servlet.multipart.max-request-size = 10MB # Tamanho máximo da solicitação. Os valores podem usar os sufixos “MB” ou “KB” para indicar megabytes ou kilobytes, respectivamente.

Estou achando bem estranho isso, de não estar funcionando

Lucas_Camara

Rapaiz, deve ter alguma camada em produção que está barrando requisições grandes, como um proxy, por exemplo.

guilhermebhte

Estou olhando com a infra

G
Solucao aceita

Você usa Nginx como Load Balancer/Reverse Proxy/etc ?

Se sim, por default o tamanho maximo de um arquivo importado é de 1MB.

Syntax:	client_max_body_size size;

Default: client_max_body_size 1m;

Context: http, server, location

Sets the maximum allowed size of the client request body. If the size in a request exceeds the configured value, the 413 (Request Entity Too Large) error is returned to the client. Please be aware that browsers cannot correctly display this error. Setting size to 0 disables checking of client request body size.

Documentação Nginx - Module ngx_http_core_module

guilhermebhte

Vendo com a pessoa da infra

Criado 9 de dezembro de 2021
Ultima resposta 14 de dez. de 2021
Respostas 29
Participantes 3