-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Closed
Labels
in: webIssues in web modules (web, webmvc, webflux, websocket)Issues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancementA general enhancement
Milestone
Description
When uploading a file that is too large (exceeding either spring.servlet.multipart.max-file-size
or spring.servlet.multipart.max-request-size
), a 500 Internal Server Error is thrown. This seems odd to me, as this is an error due to an unsupported value sent by the client, not an unexpected server issue.
It feels like a 4xx client error would be more appropriate for this situation, such as 413 Payload Too Large.
Workaround
This can be manually implemented in a Spring Boot application today by creating a custom @ExceptionHandler
for MaxUploadSizeExceededException
. If the handler is set in the controller class, the spring.servlet.multipart.resolve-lazily
property must also be set to true
:
@ExceptionHandler
public void maxUploadSizeExceeded(MaxUploadSizeExceededException e, HttpServletResponse response) throws IOException {
response.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
}
Example of current behavior
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/fileUpload")
public class FileUploadController {
@PostMapping
public String handleFileUpload(@RequestParam("file") MultipartFile file) {
return String.format("Uploaded %s (%s bytes)", file.getName(), file.getSize());
}
}
import com.fasterxml.jackson.databind.JsonNode;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.test.context.TestPropertySource;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import java.io.*;
import java.nio.file.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
class UploadTest {
@Nested
@TestPropertySource(properties = "spring.servlet.multipart.max-file-size:1000B")
class MaxFileSize extends AbstractUploadTest {
@Test
void uploadFileLargerThanMaxFileSize() {
ResponseEntity<JsonNode> response = uploadFileWithError(" ".repeat(2000).getBytes());
assertEquals(MaxUploadSizeExceededException.class.getName(), response.getBody().get("exception").textValue());
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
}
}
@Nested
@TestPropertySource(properties = "spring.servlet.multipart.max-request-size:1000B")
class MaxRequestSize extends AbstractUploadTest {
@Test
void uploadFileLargerThanMaxRequestSize() {
ResponseEntity<JsonNode> response = uploadFileWithError(" ".repeat(2000).getBytes());
assertEquals(MaxUploadSizeExceededException.class.getName(), response.getBody().get("exception").textValue());
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
}
}
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(properties = "server.error.include-exception=true")
private static abstract class AbstractUploadTest {
@Autowired
private TestRestTemplate testRestTemplate;
protected ResponseEntity<JsonNode> uploadFileWithError(byte[] bytes) {
return testRestTemplate.postForEntity("/fileUpload",
getRequestEntity(bytes), JsonNode.class);
}
private HttpEntity<LinkedMultiValueMap<String, Object>> getRequestEntity(byte[] data) {
LinkedMultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
parameters.add("file", createTempFile(data));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
return new HttpEntity<>(parameters, headers);
}
private FileSystemResource createTempFile(byte[] data) {
try {
Path file = Files.createTempFile("test", ".txt");
Files.write(file, data);
return new FileSystemResource(file);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
}
Karl255
Metadata
Metadata
Assignees
Labels
in: webIssues in web modules (web, webmvc, webflux, websocket)Issues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancementA general enhancement