Мой сервлет выполняет следующие действия для файла, переданного для загрузки через мою страницу JSP.
Шаг 1 - получить файл, всегда его изображение
Шаг 2 - проверьте, нужно ли изменить его размер
Шаг 2a - если нужно изменить размер, сделайте это
Шаг 3 - также измените размер и создайте размер миниатюры
Шаг 4 - сохранить новое измененное изображение в папке на сервере
Шаг 5 - сохранить эскиз изображения в папке на сервере
Наибольший размер изображения (по запросу моего клиента), который сервлет примет для обработки, составляет 3900 x 3900 ... Я знаю, это огромно! Но это то, что хочет клиент.
Я поставил сервлет на свой tomcat на своем vps для тестирования, и я вижу довольно серьезное потребление памяти.
Пределы памяти VPS
Я получаю 316 МБ памяти. При новом перезапуске Tomcat объем памяти составляет около 108 МБ. VPS также работает на сервере Apache.
Apache , с Tomcat STOPPED использует 45 МБ, поэтому Tomcat занимает 63 МБ при первом запуске.
Tomcat.conf - файл имеет следующий набор для кучи.
# Initial Java Heap Size (in MB)
wrapper.java.initmemory=100
# Maximum Java Heap Size (in MB)
wrapper.java.maxmemory=128
Как только я запускаю процесс загрузки изображения - отправляя файл изображения через форму на странице JSP - сервлет берет верх, выполняя шаги, которые я описал выше.
Я использую то же изображение, чтобы проверить вещи. Размер изображения составляет 3872 x 2592 пикселя, а его размер равен 2,53 МБ.
Я отправляю это изображение около 5 раз. Каждая загрузка занимает до минуты или более для завершения.
Результаты теста
1 изображение: память = 150 МБ
2 изображения: память = 179 МБ
3 изображение: 179,8
4 изображение: 188,8
5 изображение: 189,3
Почему такой скачок после загрузки изображения, которое составляет всего 2,53 МБ?
Я не понимаю Когда память падает, она падает немного. Я загрузил другое изображение после первых 5, и память пошла в 188,8.
Есть ли что-то неэффективное в моем коде? Я позаботился о том, чтобы закрыть все потоки, или, по крайней мере, я почти уверен, что сделал.
Любой вклад приветствуется.
Мой сервлет загрузки и изменения размера
public void addPhoto(Statement stmt, HttpServletRequest req, HttpServletResponse res, HttpSession session) {
BufferedInputStream bis = null;
BufferedImage bufimg = null;
BufferedImage resized = null;
ByteArrayOutputStream bytestream = null;
BufferedOutputStream bos = null;
FileOutputStream fos = null;
try {
String ImageMain = "";
String ImageThumb = "";
String dbShortPathMain = "images/gallery/";
String dbShortPathThumb = "images/gallery/";
String fileNameToLowerCase = "";
String fileExtension = "";
byte[] newimage = null;
boolean isPart = ServletFileUpload.isMultipartContent(req);
if(isPart) {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileupload = new ServletFileUpload(factory);
java.util.List items = fileupload.parseRequest(req);
Iterator it = items.iterator();
while(it.hasNext()) { //while1
FileItem item = (FileItem)it.next();
String fieldValue = item.getName();
if(!item.isFormField()) {
String fieldName = item.getFieldName();
if(fieldName.equals("ImageMain")) { //10
//--------------------------
//continue processing upload
//field wasn't blank
//---------------------------
// Create a FileItem object to access the file.
File f = new File(fieldValue);
// Get content type by filename.
String contentType = getServletContext().getMimeType(f.getName());
if(contentType == null) contentType = "none";
if(!contentType.startsWith("image")) {
appendToURL += "¬file=y";
} else {
//check size
bis = new BufferedInputStream(item.getInputStream());
//BufferedImage
bufimg = ImageIO.read(bis);
//check size of image
int img_width = bufimg.getWidth();
int img_height = bufimg.getHeight();
//not accepting images larger than 3900 x 3900
if(img_width > 3900 || img_height > 3900) {
appendToURL += "&filesize=y";
} else {
//------------------------------------------
// R E S I Z E & U P L O A D F I L E
//------------------------------------------
//#### STEP 1 - make size (600 max width) image ####
double scale = (double)maxLargeImageSize/(double)img_width;
Image sized = getScaledInstanceAWT(bufimg, scale, Image.SCALE_SMOOTH);
//convert image to BufferedImage
resized = toBufferedImage(sized, BufferedImage.TYPE_INT_RGB);
bytestream = new ByteArrayOutputStream();
//make file name characters all lowercase, and extract extension (.jpg)
fileNameToLowerCase = fieldValue.toLowerCase();
fileExtension = fileNameToLowerCase.substring(fileNameToLowerCase.indexOf(".")+1,fileNameToLowerCase.length());
//initialize buffer output stream for efficiency
//BufferedOutputStream
bos = new BufferedOutputStream(bytestream);
//W R I T E image to BufferedOutputStream and ByteArrayOutputStream
if(fileExtension.equals("png"))
ImageIO.write(resized,"png",bos);
if(fileExtension.equals("jpg"))
ImageIO.write(resized,"jpg",bos);
if(fileExtension.equals("jpeg"))
ImageIO.write(resized,"jpeg",bos);
if(fileExtension.equals("gif"))
ImageIO.write(resized,"gif",bos);
if(fileExtension.equals("bmp"))
ImageIO.write(resized,"bmp",bos);
// Flush ByteArrayOutputStream
bytestream.flush();
//convert the bytes in stream to byte array
//byte[]
newimage = bytestream.toByteArray();
//specify the file name
ImageMain = FileUploadPath+"/thenewfile."+fileExtension;
dbShortPathMain += cat+"/thenewfile."+fileExtension;
fos = new FileOutputStream(ImageMain);
fos.write(newimage);
fos.flush();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//#### STEP 2 - make Thumb size (140 max width) image ####
scale = (double)maxThumbImageSize/(double)img_height;
sized = getScaledInstanceAWT(bufimg, scale, Image.SCALE_SMOOTH);
//convert image to BufferedImage
resized = toBufferedImage(sized, BufferedImage.TYPE_INT_RGB);
//used to convert the new image to bytes so it can be put into db
//ByteArrayOutputStream
bytestream = new ByteArrayOutputStream();
//initialize buffer output stream for efficiency
//BufferedOutputStream
bos = new BufferedOutputStream(bytestream);
//W R I T E image to BufferedOutputStream and ByteArrayOutputStream
if(fileExtension.equals("png"))
ImageIO.write(resized,"png",bos);
if(fileExtension.equals("jpg"))
ImageIO.write(resized,"jpg",bos);
if(fileExtension.equals("jpeg"))
ImageIO.write(resized,"jpeg",bos);
if(fileExtension.equals("gif"))
ImageIO.write(resized,"gif",bos);
if(fileExtension.equals("bmp"))
ImageIO.write(resized,"bmp",bos);
// Flush ByteArrayOutputStream
bytestream.flush();
//convert the bytes in stream to byte array
//byte[]
newimage = bytestream.toByteArray();
//specify the file name
ImageThumb = FileUploadPath+"/newfilethumb."+fileExtension;
dbShortPathThumb += cat+"/newfilethumb."+fileExtension;
fos = new FileOutputStream(ImageThumb);
fos.write(newimage);
fos.flush();
//#### end large size ####
//---------------------------------------
}
}
}
}//isFormField
}//while
}//isPart
}//try
catch(Exception e) {}
finally {
if (bis != null) try { bis.close(); } catch (IOException logOrIgnore) {}
if (bytestream != null) try { bytestream.close(); } catch (IOException logOrIgnore) {}
if (bos != null) try { bos.close(); } catch (IOException logOrIgnore) {}
if (fos != null) try { fos.close(); } catch (IOException logOrIgnore) {}
}
}//addPhoto
//-----------------------------------------------------------
//R E S I Z I N G I M A G E M E T H O D S
//-----------------------------------------------------------
public BufferedImage toBufferedImage(Image image, int type) {
BufferedImage result = null;
try {
int w = image.getWidth(null);
int h = image.getHeight(null);
result = new BufferedImage(w, h, type);
Graphics2D g = result.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
}//try
catch(Exception e) {}
return result;
}//end
public Image getScaledInstanceAWT(BufferedImage source, double scale, int hint) {
Image newimage = null;
try {
int w = (int) (source.getWidth() * scale);
int h = (int) (source.getHeight() * scale);
newimage = source.getScaledInstance(w, h, hint);
}//try
catch(Exception e) {}
return newimage;
}//end