异常:在Spring Boot中multipart/form-data请求失败



技术栈:Java 14, Spring Boot 2.5.3, MySQL 8.0.26, JPA

我有一个春季启动上传Excel web应用程序。上传14KB的Excel文件成功。但是,如果尝试上传容量为15MB和50MB的Excel文件,则会出现以下异常:

我猜是上传时服务器连接超时了。我猜由于服务器连接时间短,在上传文件之前服务器将被关闭。为了解决这个问题,我尝试改变application.properties中的服务器设置。我找到了一些财产。但这是不合适的。IDE像这样下划线。我还访问了Spring通用应用程序属性页面以找到适当的属性,但我找不到它。

我想知道是什么原因导致了异常。我想知道这是否是解决问题的正确方法。

提前谢谢你。如果你回复,我将尽快回复。

<<p>异常控制台/strong>
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.impl.IOFileUploadException: Processing of multipart/form-data request failed. java.io.EOFException] with root cause
java.io.EOFException: null
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1294) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1206) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:805) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.Http11InputBuffer.access$300(Http11InputBuffer.java:42) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.Http11InputBuffer$SocketInputBuffer.doRead(Http11InputBuffer.java:1172) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:101) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.Http11InputBuffer.doRead(Http11InputBuffer.java:249) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.Request.doRead(Request.java:640) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:317) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.InputBuffer.checkByteBufferEof(InputBuffer.java:600) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:340) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:132) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:132) ~[na:na]
at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:132) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.tomcat.util.http.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:975) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.tomcat.util.http.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:879) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:132) ~[na:na]
at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:132) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:106) ~[na:na]
at org.apache.tomcat.util.http.fileupload.util.Streams.copy(Streams.java:98) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:291) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.Request.parseParts(Request.java:2922) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.Request.getParts(Request.java:2824) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1098) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:95) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:88) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:122) ~[spring-web-5.3.9.jar:5.3.9]
at ...

application.properties

server.tomcat.connection-timeout是正确的。但server.tomcat.disable-upload-timeoutserver.connectionUploadTimeout不适宜。

server.tomcat.connection-timeout=5000
server.tomcat.disable-upload-timeout=false
server.connectionUploadTimeout=5000
# MultiPart
spring.servlet.multipart.max-file-size=50MB
spring.servlet.multipart.max-request-size=50MB

控制器

package com.nc.ojtfirstproject.web;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import com.nc.ojtfirstproject.message.ResponseMessage;
import com.nc.ojtfirstproject.service.StandardProductService;
@Controller
public class StandardProductController {

private final StandardProductService standardProductService;
public StandardProductController(StandardProductService standardProductService) {
this.standardProductService = standardProductService;
}
@PostMapping("/excel/upload")
public ResponseEntity<ResponseMessage> uploadFile(@RequestParam("file") MultipartFile file) {
String TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpStatus status = HttpStatus.OK;
String message = "";
if (TYPE.equals(file.getContentType())) {
try {
standardProductService.save(file);
status = HttpStatus.OK;
message = "success: " + file.getOriginalFilename();
} catch (Exception e) {
status = HttpStatus.EXPECTATION_FAILED;
message = "fail: " + file.getOriginalFilename();
}
} else {
status = HttpStatus.BAD_REQUEST;
message = "Please upload excel file";
}
return ResponseEntity.status(status).body(new ResponseMessage(message));
}
}

package com.nc.ojtfirstproject.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.nc.ojtfirstproject.domain.standardProduct.StandardProduct;
import com.nc.ojtfirstproject.domain.standardProduct.StandardProductRepository;
@Service
public class StandardProductService {
private final StandardProductRepository standardProductRepository;
public StandardProductService(StandardProductRepository standardProductRepository) {
this.standardProductRepository = standardProductRepository;
}
@Transactional
public void save(MultipartFile file) {
final int TRANSACTION_CHUNK_LIMIT = 10000;
List<StandardProduct> standardProductList = new ArrayList<StandardProduct>();
try {
Workbook workbook = new XSSFWorkbook(file.getInputStream());
Sheet sheet = workbook.getSheetAt(0);

for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++) {
Row row = sheet.getRow(i);
StandardProduct standardProduct = new StandardProduct();

standardProduct.setCode((int) row.getCell(0).getNumericCellValue());
standardProduct.setCategoryCode((int) row.getCell(1).getNumericCellValue());
standardProduct.setName(row.getCell(2).getStringCellValue());
standardProduct.setLowestPrice((int) row.getCell(3).getNumericCellValue());
standardProduct.setMobileLowestPrice((int) row.getCell(4).getNumericCellValue());
standardProduct.setAveragePrice((int) row.getCell(5).getNumericCellValue());
standardProduct.setCompanies((int) row.getCell(6).getNumericCellValue());
standardProductList.add(standardProduct);

// TRANSACTION_CHUNK_LIMIT saveAll()
if (TRANSACTION_CHUNK_LIMIT == standardProductList.size()) {
standardProductRepository.saveAll(standardProductList);
standardProductList.clear();
System.out.println(TRANSACTION_CHUNK_LIMIT + " success");
}
}

workbook.close();

} catch (IOException e) {
throw new RuntimeException("save fail: " + e.getMessage());
}
// TRANSACTION_CHUNK_LIMIT saveAll()
try {
standardProductRepository.saveAll(standardProductList);
} catch (Exception e) {
throw new RuntimeException("save fail: " + e.getMessage());
}
}
}

build.gradle

plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.nc'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '14'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'io.springfox:springfox-boot-starter:3.0.0'
implementation 'org.apache.poi:poi:4.1.2'
implementation 'org.apache.poi:poi-ooxml:4.1.2'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}

我有类似的错误,并更新了application.properties文件中的以下配置参数,如下所示:

spring.servlet.multipart.max-file-size=XX MB
spring.servlet.multipart.max-request-size=XX MB
server.tomcat.connectionUploadTimeout=XXX (in miliseconds)
server.tomcat.connectionTimeout=XXX (in miliseconds)
server.tomcat.connection-timeout=XXX (in miliseconds)
server.tomcat.max-swallow-size=XX MB
server.tomcat.max-http-form-post-size=XX MB
server.tomcat.background-processor-delay=XXX (in miliseconds)
server.tomcat.keep-alive-timeout=XXX (in miliseconds)
server.tomcat.max-swallow-size=XXX MB

按图示设置这些参数应该可以解决问题。

最新更新