CKFinder上傳TIFF格式圖片

TIFF屬於一種高清圖片格式,分辨率很是高,在CKFinder上傳中會出現問題,查閱CF源碼發現使用ImageIO上傳圖片數據,通常的JPG等格式是徹底沒問題的,可是在上傳TIFF格式且提交較大時(達到1M以上就會報錯,可是其餘格式的徹底不會)會報錯內存溢出,但不是顯示具體錯誤信息。java

咱們先採用兩種方式解決問題:apache

第一種方式,就是修改CF的源代碼,在上傳TIFF格式圖片的時候,保留TIFF格式的圖片,同時將其轉換爲JPG格式的圖片,這個是沒有任何問題的。this

第二種方式,還沒有實現,須要解決CF縮略圖模式下TIFF不支持預覽問題。google

CKFinder版本:2.3url

解決方法一:TIFF數據格式圖片轉換JPG格式,同時保留原格式TIFF

WEB-INF/ckfinder.xml,添加tif格式,容許上傳tif格式圖片數據。spa

<type name="images">
			<url>%BASE_URL%images/</url>
			<directory>%BASE_DIR%images</directory>
			<maxSize>100M</maxSize>
			<allowedExtensions>bmp,gif,jpeg,jpg,png,tif</allowedExtensions>
			<deniedExtensions></deniedExtensions>
		</type>
  • 下載CKFinder 2.3版本的java源代碼(注意對應Jeesite裏面的版本),地址以下:
  • https://ckeditor.com/ckeditor-4/ckfinder/changelog/
  • 直接將整個類文件複製到工程中,包含完整的包路徑。
  • 這裏只要關注ImageIO這個方法,由於只要涉及到此方法都會報錯,因此在ImageIO運行前就作格式判斷,並強制取消對TIFF格式的數據驗證,在createTmpThumb方法中,這裏對圖片進行上傳操做,因此單獨對TIFF格式數據進行格式轉換成JPG進行存儲便可。

PS:目前只作簡單的處理,只能說勉強能用,後續再對第二種方法進行研究。code

/*
 * CKFinder
 * ========
 * http://ckfinder.com
 * Copyright (C) 2007-2012, CKSource - Frederico Knabben. All rights reserved.
 *
 * The software, this file and its contents are subject to the CKFinder
 * License. Please read the license.txt file before using, installing, copying,
 * modifying or distribute this file or part of its contents. The contents of
 * this file is part of the Source Code of CKFinder.
 */
package com.ckfinder.connector.utils;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;

import javax.imageio.ImageIO;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;

import net.coobird.thumbnailator.Thumbnails;

import org.apache.commons.fileupload.FileItem;

import com.ckfinder.connector.configuration.IConfiguration;
import com.sun.media.jai.codec.FileCacheSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.JPEGEncodeParam;
import com.sun.media.jai.codec.TIFFEncodeParam;

/**
 * Utils to operate on images.
 */
public class ImageUtils {

	/**
	 * allowed image extensions.
	 */
	private static final String[] ALLOWED_EXT = { "gif", "jpeg", "jpg", "png",
			"psd", "bmp", "tiff", "tif", "swc", "jpc", "jp2", "jpx", "jb2",
			"xbm", "wbmp" };
	private static final int MAX_BUFF_SIZE = 1024;
	
	private static boolean prefix_tiff = false;

	/**
	 * Resizes the image and writes it to the disk.
	 *
	 * @param sourceImage
	 *            orginal image file.
	 * @param width
	 *            requested width
	 * @param height
	 *            requested height
	 * @param quality
	 *            requested destenation file quality
	 * @param destFile
	 *            file to write to
	 * @throws IOException
	 *             when error occurs.
	 */
	private static void resizeImage(final BufferedImage sourceImage, final int width,
									final int height, final float quality,
									final File destFile) throws IOException {
		try {
			Thumbnails.of(sourceImage).size(width, height).keepAspectRatio(false)
			.outputQuality(quality).toFile(destFile);
			// for some special files outputQuality couses error:
			//IllegalStateException inner Thumbnailator jar. When exception is thrown
			// image is resized without quality
			// When http://code.google.com/p/thumbnailator/issues/detail?id=9 
			// will be fixed this try catch can be deleted. Only:
			//Thumbnails.of(sourceImage).size(width, height).keepAspectRatio(false)
			//	.outputQuality(quality).toFile(destFile);
			// should remain.
		} catch (IllegalStateException e) {
			Thumbnails.of(sourceImage).size(width, height).keepAspectRatio(false)
						.toFile(destFile);
		}
	}

	/**
	 * create thumb file.
	 *
	 * @param orginFile
	 *            orgin image file.
	 * @param file
	 *            file to save thumb
	 * @param conf
	 *            connector configuration
	 * @throws IOException
	 *             when error occurs.
	 */
	public static void createThumb(final File orginFile, final File file,
			final IConfiguration conf) throws IOException {
		BufferedImage image = ImageIO.read(orginFile);
		if (image != null) {
			Dimension dimension = createThumbDimension(image,
					conf.getMaxThumbWidth(), conf.getMaxThumbHeight());
			FileUtils.createPath(file, conf, true);
			if (image.getHeight() == dimension.height
					&& image.getWidth() == dimension.width) {
				writeUntouchedImage(orginFile, file);
			} else {
				resizeImage(image, dimension.width, dimension.height,
						conf.getThumbsQuality(), file);
			}
		} else {
			if (conf.isDebugMode()) {
				throw new IOException("Wrong image file");
			}
		}

	}

	/**
	 * Uploads image and if the image size is larger than maximum allowed it
	 * resizes the image.
	 *
	 * @param stream
	 *            input stream.
	 * @param file
	 *            file name
	 * @param fileName
	 *            name of file
	 * @param conf
	 *            connector configuration
	 * @throws IOException
	 *             when error occurs.
	 * 20180105 update method - upload 2 files, one of JPEG, one of TIFF
	 */
	public static void createTmpThumb(final InputStream stream,
			final File file, final String fileName, final IConfiguration conf)
			throws IOException {
		if(prefix_tiff){
//			System.out.println(file.getAbsolutePath());
//			System.out.println(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")));
			FileCacheSeekableStream stream1 = new FileCacheSeekableStream(stream);  
			PlanarImage in = JAI.create("stream", stream1);      
			String newFilePath = file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + ".jpg";
			OutputStream osJPEG = new FileOutputStream(newFilePath);
			JPEGEncodeParam JPEGparam = new JPEGEncodeParam();		
			ImageEncoder encJPEG = ImageCodec.createImageEncoder("JPEG", osJPEG, JPEGparam); 
			OutputStream osTIFF = new FileOutputStream(file);
			TIFFEncodeParam TIFFparam = new TIFFEncodeParam();  
			TIFFparam.setCompression(TIFFEncodeParam.COMPRESSION_NONE); 
			ImageEncoder encTIFF = ImageCodec.createImageEncoder("TIFF", osTIFF, TIFFparam); 
            try {  
	               encJPEG.encode(in);
	               osJPEG.flush();  
	               osJPEG.close();   
            	   encTIFF.encode(in);
		           osTIFF.flush();  
		           osTIFF.close();   
		           stream.close();  
		       } catch (IOException e) {                  
		    	   throw new IOException("Wrong file");
		       }
		} else {
			BufferedInputStream bufferedIS = new BufferedInputStream(stream);
			bufferedIS.mark(Integer.MAX_VALUE);
			BufferedImage image = ImageIO.read(bufferedIS);
			if (image == null) {
				throw new IOException("Wrong file");
			}
			Dimension dimension = createThumbDimension(image, conf.getImgWidth(),
					conf.getImgHeight());
			if (image.getHeight() == dimension.height
					&& image.getWidth() == dimension.width) {
				bufferedIS.reset();
				writeUntouchedImage(bufferedIS, file);
			} else {
				resizeImage(image, dimension.width, dimension.height,
						conf.getImgQuality(), file);
			}
			stream.close();
		}
	}

	/**
	 * Creates image file with fixed width and height.
	 *
	 * @param sourceFile
	 *            input file
	 * @param destFile
	 *            file to save
	 * @param width
	 *            image width
	 * @param height
	 *            image height
	 * @param quality
	 *            image quality
	 * @throws IOException
	 *             when error occurs.
	 */
	public static void createResizedImage(final File sourceFile,
			final File destFile, final int width, final int height,
			final float quality) throws IOException {
		
		BufferedImage image = ImageIO.read(sourceFile);
		Dimension dimension = new Dimension(width, height);
		if (image.getHeight() == dimension.height
				&& image.getWidth() == dimension.width) {
			writeUntouchedImage(sourceFile, destFile);
		} else {
			resizeImage(image, dimension.width, dimension.height, quality,
					destFile);

		}

	}

	/**
	 * creates dimension of thumb.
	 *
	 * @param image
	 *            orginal image.
	 * @param maxWidth
	 *            max thumb width
	 * @param maxHeight
	 *            max thumb height
	 * @return dimension of thumb image.
	 */
	private static Dimension createThumbDimension(final BufferedImage image,
			final int maxWidth, final int maxHeight) {
		Dimension dimension = new Dimension();
		if (image.getWidth() >= image.getHeight()) {
			if (image.getWidth() >= maxWidth) {
				dimension.width = maxWidth;
				dimension.height = Math.round(((float) maxWidth / image
						.getWidth()) * image.getHeight());
			} else {
				dimension.height = image.getHeight();
				dimension.width = image.getWidth();
			}
		} else {
			if (image.getHeight() >= maxHeight) {
				dimension.height = maxHeight;
				dimension.width = Math.round((((float) maxHeight / image
						.getHeight()) * image.getWidth()));
			} else {
				dimension.height = image.getHeight();
				dimension.width = image.getWidth();
			}
		}
		return dimension;
	}

	/**
	 * checks if file is image.
	 *
	 * @param file
	 *            file to check
	 * @return true if file is image.
	 */
	public static boolean isImage(final File file) {
		List<String> list = Arrays.asList(ALLOWED_EXT);
		String fileExt = null;
		if (file != null) {
			fileExt = FileUtils.getFileExtension(file.getName().toLowerCase());
			return (fileExt != null) ? list.contains(fileExt) : false;
		} else {
			return false;
		}
	}

	/**
	 * check if image size isn't bigger then bigest allowed.
	 *
	 * @param stream
	 *            temp file input stream.
	 * @param conf
	 *            connector configuration.
	 * @return true if image size isn't bigger then bigest allowe.
	 * @throws IOException
	 *             when error occurs during reading image.
	 */
	public static boolean checkImageSize(final InputStream stream,
			final IConfiguration conf) throws IOException {
		if(!prefix_tiff){
			BufferedImage bi = ImageIO.read(stream);
			stream.close();
			if (bi == null) {
				return false;
			}
			if (bi.getHeight() > conf.getImgHeight()
					|| bi.getWidth() > conf.getImgWidth()) {
				return false;
			}
		}
		return true;
	}

	/**
	 * checks if image file is image.
	 *
	 * @param item
	 *            file upload item
	 * @return true if file is image.
	 */
	public static boolean checkImageFile(final FileItem item) {
		BufferedImage bi;
		InputStream is = null;
		if(item.getContentType().equals("image/tiff")){
			prefix_tiff = true;
			return true;
		} else {
			prefix_tiff = false;
			try {
				is = item.getInputStream();
				bi = ImageIO.read(is);
			} catch (IOException e) {
				return false;
			} finally {
				if (is != null){
					try { is.close(); } catch (Exception e) {}	
				}			
			}
			return (bi != null);
		}
	}

	/**
	 * writes unchanged file to disk.
	 *
	 * @param sourceFile
	 *            - file to read from
	 *
	 * @param destFile
	 *            - file to write to
	 *
	 * @throws IOException
	 *             when error occurs.
	 */
	private static void writeUntouchedImage(final File sourceFile, final File destFile)
			throws IOException {
		FileInputStream fileIS = new FileInputStream(sourceFile);
		writeUntouchedImage(fileIS, destFile);
	}

	/**
	 * writes unchanged file to disk.
	 *
	 * @param stream
	 *            - stream to read the file from
	 *
	 * @param destFile
	 *            - file to write to
	 *
	 * @throws IOException
	 *             when error occurs.
	 */
	private static void writeUntouchedImage(final InputStream stream, final File destFile)
			throws IOException {
		ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
		byte[] buffer = new byte[MAX_BUFF_SIZE];
		int readNum = -1;
		while ((readNum = stream.read(buffer)) != -1) {
			byteArrayOS.write(buffer, 0, readNum);
		}
		byte[] bytes = byteArrayOS.toByteArray();
		byteArrayOS.close();
		FileOutputStream fileOS = new FileOutputStream(destFile);
		fileOS.write(bytes);
		fileOS.flush();
		fileOS.close();
	}
	
	
}
相關文章
相關標籤/搜索