Spring Boot: Apache Commons File Upload를 사용한 대용량 스트리밍 파일 업로드
'스트리밍' Apache Commons File Upload API를 사용하여 대용량 파일을 업로드하려고 합니다.
Apache Commons File Uploader를 사용하는 이유는 기본 Spring Multipart Uploader가 아닌 매우 큰 파일 크기(약 2GB)를 업로드하면 오류가 발생하기 때문입니다.저는 GIS 어플리케이션에서 작업하고 있습니다.이 어플리케이션에서는 파일을 업로드 할 수 있습니다.
파일 업로드 컨트롤러의 전체 코드는 다음과 같습니다.
@Controller
public class FileUploadController {
@RequestMapping(value="/upload", method=RequestMethod.POST)
public void upload(HttpServletRequest request) {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
// Inform user about invalid request
return;
}
//String filename = request.getParameter("name");
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();
// Parse the request
try {
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (item.isFormField()) {
System.out.println("Form field " + name + " with value " + Streams.asString(stream) + " detected.");
} else {
System.out.println("File field " + name + " with file name " + item.getName() + " detected.");
// Process the input stream
OutputStream out = new FileOutputStream("incoming.gz");
IOUtils.copy(stream, out);
stream.close();
out.close();
}
}
}catch (FileUploadException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
@RequestMapping(value = "/uploader", method = RequestMethod.GET)
public ModelAndView uploaderPage() {
ModelAndView model = new ModelAndView();
model.setViewName("uploader");
return model;
}
}
문제는...getItemIterator(request)
는항상항목이없는반복기를반환합니다(즉,iter.hasNext()
)는 항상 반환됩니다.false
.
application.properties 파일은 다음과 같습니다.
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:19095/authdb
spring.datasource.username=georbis
spring.datasource.password=asdf123
logging.level.org.springframework.web=DEBUG
spring.jpa.hibernate.ddl-auto=update
multipart.maxFileSize: 128000MB
multipart.maxRequestSize: 128000MB
server.port=19091
의 JSP 뷰/uploader
는 다음과 같습니다.
<html>
<body>
<form method="POST" enctype="multipart/form-data" action="/upload">
File to upload: <input type="file" name="file"><br />
Name: <input type="text" name="name"><br /> <br />
Press here to upload the file!<input type="submit" value="Upload">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</body>
</html>
제가 뭘 잘못하고 있는 걸까요?
M의 매우 도움이 되는 코멘트 덕분입니다.디넘, 내가 문제를 해결했어저는 저의 원래 게시물을 정리했고, 나중에 참조할 수 있도록 완전한 답변으로 이 글을 올립니다.
첫 번째 실수는 디폴트를 무효로 하지 않은 것입니다.MultipartResolver
그 봄이 제공하는 것.이는 결국 리졸바(Resolver)가 처리하게 되었습니다.HttpServeletRequest
컨트롤러가 동작하기 전에 소비하는 것입니다.
M덕분에 비활성화하는 방법.Deinum은 다음과 같습니다.
multipart.enabled=false
하지만, 그 이후에도 또 다른 함정이 나를 기다리고 있었다.디폴트 멀티파트 리졸버를 무효로 하자마자 업로드를 시도할 때 다음 오류가 표시되기 시작했습니다.
Fri Sep 25 20:23:47 IST 2015
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
시큐러티 설정에서는, CSRF 보호가 유효하게 되어 있었습니다.그 때문에, 이하의 방법으로 POST 요구를 송신할 필요가 있었습니다.
<html>
<body>
<form method="POST" enctype="multipart/form-data" action="/upload?${_csrf.parameterName}=${_csrf.token}">
<input type="file" name="file"><br>
<input type="submit" value="Upload">
</form>
</body>
</html>
컨트롤러도 조금 수정했습니다.
@Controller
public class FileUploadController {
@RequestMapping(value="/upload", method=RequestMethod.POST)
public @ResponseBody Response<String> upload(HttpServletRequest request) {
try {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
// Inform user about invalid request
Response<String> responseObject = new Response<String>(false, "Not a multipart request.", "");
return responseObject;
}
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();
// Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (!item.isFormField()) {
String filename = item.getName();
// Process the input stream
OutputStream out = new FileOutputStream(filename);
IOUtils.copy(stream, out);
stream.close();
out.close();
}
}
} catch (FileUploadException e) {
return new Response<String>(false, "File upload error", e.toString());
} catch (IOException e) {
return new Response<String>(false, "Internal server IO error", e.toString());
}
return new Response<String>(true, "Success", "");
}
@RequestMapping(value = "/uploader", method = RequestMethod.GET)
public ModelAndView uploaderPage() {
ModelAndView model = new ModelAndView();
model.setViewName("uploader");
return model;
}
}
여기서 Response는 내가 사용하는 단순한 범용 응답 유형입니다.
public class Response<T> {
/** Boolean indicating if request succeeded **/
private boolean status;
/** Message indicating error if any **/
private String message;
/** Additional data that is part of this response **/
private T data;
public Response(boolean status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}
// Setters and getters
...
}
최신 버전의 스프링 부트를 사용하고 있는 경우(저는 2.0.0을 사용하고 있습니다).M7) 그러면 속성 이름이 변경되었습니다.봄은 테크놀로지 고유의 이름을 사용하기 시작했습니다.
spring.servlet.multipart.maxFileSize=-1
spring.servlet.multipart.maxRequestSize=-1
spring.servlet.servart.enabled=false
여러 구현이 활성화되어 Stream Closed 예외가 발생하는 경우 마지막 옵션을 사용하면 기본 스프링 구현을 비활성화할 수 있습니다.
추가해 보세요spring.http.multipart.enabled=false
application.properties 파일에 저장됩니다.
킨디터+스프링부츠를 사용합니다.(MultipartHttpServletRequest) 요구를 사용하는 경우.파일을 가져올 수 있었지만 apeche-common-io:upload.parse(request)를 사용하여 반환값이 null입니다.
public BaseResult uploadImg(HttpServletRequest request,String type){
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultiValueMap<String, MultipartFile> multiFileMap = multipartRequest.getMultiFileMap();
스프링 속성을 추가할 수 있습니다.
spring.servlet.multipart.max-file-size=20000KB
spring.servlet.multipart.max-request-size=20000KB
여기서 나의 최대 파일 사이즈는 20000KB입니다.필요에 따라서 변경할 수 있습니다.
언급URL : https://stackoverflow.com/questions/32782026/springboot-large-streaming-file-upload-using-apache-commons-fileupload
'IT' 카테고리의 다른 글
리액트로 에이잭스 처리 (0) | 2023.03.04 |
---|---|
쇼트 코드를 사용하여 워드프레스 투고의 페이지 제목을 콘텐츠에 포함시키는 방법 (0) | 2023.03.04 |
Spring 3 요청 맵핑:경로 값 가져오기 (0) | 2023.03.04 |
JSON 개체 스트림을 jq를 사용하여 배열로 변환하는 방법 (0) | 2023.03.04 |
TypeScript 컴파일의 실험용 장식자 경고 (0) | 2023.03.04 |