Tôi đang phát triển dịch vụ gửi biểu mẫu với Jersey 2.0. Biểu mẫu bao gồm một số trường văn bản và một trường tệp. Tôi cần trích xuất tệp, tên tệp, loại phương tiện tệp và loại nội dung tệp và lưu chúng trong cửa hàng đối tượng.Tải lên tệp dịch vụ Jersey khiến OutOfMemoryError
@Path("upload")
@Consumes({MediaType.MULTIPART_FORM_DATA})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class UploadService {
@POST
public BlobDo uploadFile(FormDataMultiPart uploadedBody) {
String accountSid = uploadedBody.getField("account-sid").getValue();
String apiToken = uploadedBody.getField("api-token").getValue();
String checksum = uploadedBody.getField("checksum").getValue();
FormDataBodyPart bodyPart = uploadedBody.getField("file");
MySwiftObject obj = new MySwiftObject(bodyPart.getValueAs(InputStream.class));
obj.setName(bodyPart.getContentDisposition().getFileName());
obj.setContentType(bodyPart.getMediaType().toString());
obj.setContentDisposition(bodyPart.getContentDisposition().toString());
...
}
pom.xml
<jersey.version>2.17</jersey.version>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-inmemory</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
</dependency>
yêu cầu nộp mẫu đơn
POST /nbs/v2/upload HTTP/1.1
Host: 127.0.0.1:8080
Cache-Control: no-cache
Postman-Token: a4c1d4e9-5f71-2321-3870-e9cac0524f8d
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryA2Z9pPMA7y3da8BG
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="account-sid"
Q45Ppm5ukvdqjTQ6eW0O5ztTXipwnjKQx1p6cf+fbCQ=
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="api-token"
6397cd691909fdc14cef67dbc1dc2dc3
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="file"; filename="screen_4_100155.jpg"
Content-Type: image/jpeg
......Exif..MM.*.............................b...........j
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="checksum"
6a3381b1d16bded4a3dfc325a8bb800e
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
JVM heap size
-Xmx=1024mb
Các vấn đề
khi tải lên ~ 50MB tập hai tập tin tạm thời với số tiền MD5 tương tự được tạo ra trong thư mục /tmp/tomcat7-tomcat7-tmp
với tên FileBackedOutputStream7949386530699987086.tmp
và MIME8234229766850016150.tmp
Trước khi upload xong máy chủ ném ngoại lệ
javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.OutOfMemoryError: Java heap space org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:421) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:386) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:222)
và xóa các tập tin với tên MIME8234229766850016150.tmp
nhưng để lại cái còn lại. Và chưa xóa FileBackedOutputStream....tmp
tệp lấp đầy toàn bộ dung lượng trên ổ đĩa cứng.
Những gì tôi đã làm
gian Tăng heap để 7GB, nhưng ~ file 200MB không thể được tải lên.
Chạy công việc trên máy chủ để xóa các tệp tạm thời cũ.
tập tin tạo với tên
jersey-multipart-config.properties
và nội dungjersey.config.multipart.bufferThreshold = -1
File MIME[random numbers].tmp
không còn được tạo ra, nhưng FileBackedOutputStream[random number].tmp
vẫn treo trên ổ cứng trừ khi tomcat được khởi động lại.
Câu hỏi
Làm thế nào Jersey có thể xử lý file lớn (có thể 1GB) mà không để lại các file tạm thời trên đĩa cứng của tôi? Trường hợp tốt nhất sẽ không được sử dụng ổ cứng và chuyển các phần nhỏ thông qua bộ nhớ.
Tại sao tôi nhận được tràn heap nếu luồng đầu vào được sao lưu bằng tệp?
liệu tôi đọc
- Các đóng lời giải thích tôi thấy cho đến nay. read
- Anh chàng này có vấn đề tương tự nhưng ở phía khách hàng. read
- Có thể chứa giải pháp, nhưng không thể hiểu câu trả lời. read
- Khá gần với sự cố của tôi nhưng không thể giải quyết được. read
- bufferThanh toán ý tưởng được lấy từ đây. read