5

Tôi nhận được OutOfMemoryErrors khi tải các tệp lớn (> 300MB) lên một servlet sử dụng Commons FileUpload 1.2.1. Nó có vẻ kỳ lạ, bởi vì toàn bộ các điểm của việc sử dụng DiskFileItem là để ngăn chặn (có thể lớn) tập tin từ cư trú trong bộ nhớ. Tôi đang sử dụng kích thước mặc định là ngưỡng 10KB, vì vậy, đó là tất cả những gì nên được tải vào heap , đúng không? Đây là dấu vết ngăn xếp từng phần:Làm thế nào tôi có thể tránh được OutOfMemoryErrors khi sử dụng FileFileItem của Commons FileUpload để tải lên các tệp lớn?

java.lang.OutOfMemoryError 
     at java.io.FileInputStream.readBytes(Native Method) 
     at java.io.FileInputStream.read(FileInputStream.java:177) 
     at org.apache.commons.fileupload.disk.DiskFileItem.get(DiskFileItem.java:334) 
     at org.springframework.web.multipart.commons.CommonsMultipartFile.getBytes(CommonsMultipartFile.java:114) 

Tại sao điều này lại xảy ra? Có một số cấu hình tôi đang thiếu? Bất kỳ mẹo/thủ thuật nào để tránh tình huống này bên cạnh việc tăng kích thước heap của tôi?

Tôi thực sự không cần phải tăng heap của tôi, bởi vì trong lý thuyết nhất mà nên được nạp vào bộ nhớ từ hoạt động này là một ít hơn 10KB. Plus, tối đa heap của tôi (-Xmx) đã được thiết lập cho 1GB mà nên được rất nhiều.

Trả lời

10

Khi xử lý tệp tải lên, đặc biệt là tệp lớn, bạn nên xử lý các tệp đó dưới dạng luồng mà bạn đã đưa vào bộ đệm trong bộ nhớ kích thước trung bình và sao chép trực tiếp vào tệp đầu ra của bạn. Cách sai lầm để làm điều đó là hít toàn bộ thứ vào bộ nhớ trước khi viết nó ra.

The doc on commons-upload đề cập, ngay dưới chính giữa, cách "Xử lý tải tệp lên". Nếu bạn nhớ sao chép từ inputstream đến outputstream trong các khối có kích thước hợp lý (nói, 1 MB), bạn sẽ không có vấn đề gì.

+1

Lúc đầu, tôi không nghĩ rằng bình luận của bạn áp dụng cho hoàn cảnh của tôi bởi vì tôi không xử lý tệp trực tiếp; Tôi đã gói các cá thể FileItem trong lớp MultipartFile của Spring. Tuy nhiên, tôi đã xem xét kỹ mã nguồn hơn và nó đã gọi hàm getBytes của MultipartFile() trả về toàn bộ nội dung của tệp. Tôi đã mở FileItem của tôi khỏi MultipartFile, sau đó xử lý các tệp như được đề xuất trong tài liệu. Điều này giải quyết được vấn đề của tôi. – rcampbell

Các vấn đề liên quan