/** * 判斷文件是否為圖片<br> * <br> * @param pInput 文件名<br> * @param pImgeFlag 判斷具體文件類型<br> * @return 檢查后的結(jié)果<br> * @throws Exception */ public static boolean isPicture(String pInput, String pImgeFlag) throws Exception{ // 文件名稱為空的場(chǎng)合 if(Check.isNull(pInput)){ // 返回不和合法 return false; } // 獲得文件后綴名 String tmpName = pInput.substring(pInput.lastIndexOf(".") + 1, pInput.length()); // 聲明圖片后綴名數(shù)組 String imgeArray [][] = { {"bmp", "0"}, {"dib", "1"}, {"gif", "2"}, {"jfif", "3"}, {"jpe", "4"}, {"jpeg", "5"}, {"jpg", "6"}, {"png", "7"} ,{"tif", "8"}, {"tiff", "9"}, {"ico", "10"} }; // 遍歷名稱數(shù)組 for(int i = 0; i<imgeArray.length;i++){ // 判斷單個(gè)類型文件的場(chǎng)合 if(! Check.isNull(pImgeFlag) && imgeArray [i][0].equals(tmpName.toLowerCase()) && imgeArray [i][1].equals(pImgeFlag)){ return true; } // 判斷符合全部類型的場(chǎng)合 if(Check.isNull(pImgeFlag) && imgeArray [i][0].equals(tmpName.toLowerCase())){ return true; } } return false; } 一、通常情況下,驗(yàn)證一個(gè)文件是否圖片,可以通過(guò)以下三種方式: 1)、判斷文件的擴(kuò)展名是否是要求的圖片擴(kuò)展名 這種判斷是用得比較多的一種方式,不過(guò)這種方式非常的不妥,別人稍微的把一個(gè)不是圖片的文件的擴(kuò)展名修改為圖片的擴(kuò)展名,就繞開了你的這種校驗(yàn),如果這上傳的文件是shell、PHP或者jsp,那你的網(wǎng)站基本上可以說(shuō)就在別人的手里面了。 不過(guò)這種判斷方式也不是完全沒(méi)有用,我們可以把它放在判斷圖片的最外層,如果一個(gè)文件連擴(kuò)展名都不是我們所要求的圖片擴(kuò)展名,那就根本不用后面的內(nèi)容格式檢查了,從一定程度上說(shuō),對(duì)減少服務(wù)器的壓力還是有一定的幫助,否則所有的文件都等上傳完后成后再通過(guò)服務(wù)器去判斷,那會(huì)在一定程度上浪費(fèi)器資源的。 2)、根據(jù)文件的前面幾個(gè)字節(jié),即常說(shuō)的魔術(shù)數(shù)字進(jìn)行判斷,不同文件類型的開頭幾個(gè)字節(jié),可以查看我的另外一篇專站介紹:表示不同文件類型的魔術(shù)數(shù)字。 但是這種判斷方式也是非常不靠譜的,因?yàn)樗荒軌蝌?yàn)證文件的前面幾個(gè)字節(jié),如此時(shí)有人把一個(gè)可執(zhí)行的php文件的擴(kuò)展名修改為PNG,然后再在前面補(bǔ)上”89 50″兩個(gè)字節(jié),就又繞開了這種驗(yàn)證方式。 以下是一段通過(guò)Java代碼獲取文件前面兩個(gè)字節(jié)的示例程序: import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class ImageTypeCheck { public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } public static void main(String[] args) throws IOException { String imagePath = "c:/favicon.png"; File image = new File(imagePath); InputStream is = new FileInputStream(image); byte[] bt = new byte[2]; is.read(bt); System.out.println(bytesToHexString(bt)); } } 不過(guò)這種判斷方式和判斷擴(kuò)展名一樣,也不是完全沒(méi)有用,至少可以在前期在簡(jiǎn)單的檢查,為進(jìn)入下一步檢查做鋪墊。 3)、獲取圖片的寬高屬性 /** * 通過(guò)讀取文件并獲取其width及height的方式,來(lái)判斷判斷當(dāng)前文件是否圖片,這是一種非常簡(jiǎn)單的方式。 * * @param imageFile * @return */ public static boolean isImage(File imageFile) { if (!imageFile.exists()) { return false; } Image img = null; try { img = ImageIO.read(imageFile); if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) { return false; } return true; } catch (Exception e) { return false; } finally { img = null; } } 二、圖片文件的安全檢查處理 這就是在一張正常的圖片末尾增加的一些iframe代碼,我曾經(jīng)嘗試過(guò)單獨(dú)打開這張圖片,也將這張圖片放于網(wǎng)頁(yè)上打開,雖然這樣都不會(huì)被執(zhí)行,但并不代表插入其它的代碼也并不會(huì)執(zhí)行,殺毒軟件(如AVAST)對(duì)這種修改是會(huì)報(bào)為病毒的。 /** * 添加圖片水印 * * @param srcImg 目標(biāo)圖片路徑,如:C:\\kutuku.jpg * @param waterImg 水印圖片路徑,如:C:\\kutuku.png * @param x 水印圖片距離目標(biāo)圖片左側(cè)的偏移量,如果x<0, 則在正中間 * @param y 水印圖片距離目標(biāo)圖片上側(cè)的偏移量,如果y<0, 則在正中間 * @param alpha 透明度(0.0 -- 1.0, 0.0為完全透明,1.0為完全不透明) * @throws IOException */ public final static void addWaterMark(String srcImg, String waterImg, int x, int y, float alpha) throws IOException { // 加載目標(biāo)圖片 File file = new File(srcImg); String ext = srcImg.substring(srcImg.lastIndexOf(".") + 1); Image image = ImageIO.read(file); int width = image.getWidth(null); int height = image.getHeight(null); // 將目標(biāo)圖片加載到內(nèi)存。 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = bufferedImage.createGraphics(); g.drawImage(image, 0, 0, width, height, null); // 加載水印圖片。 Image waterImage = ImageIO.read(new File(waterImg)); int width_1 = waterImage.getWidth(null); int height_1 = waterImage.getHeight(null); // 設(shè)置水印圖片的透明度。 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); // 設(shè)置水印圖片的位置。 int widthDiff = width - width_1; int heightDiff = height - height_1; if (x < 0) { x = widthDiff / 2; } else if (x > widthDiff) { x = widthDiff; } if (y < 0) { y = heightDiff / 2; } else if (y > heightDiff) { y = heightDiff; } // 將水印圖片“畫”在原有的圖片的制定位置。 g.drawImage(waterImage, x, y, width_1, height_1, null); // 關(guān)閉畫筆。 g.dispose(); // 保存目標(biāo)圖片。 ImageIO.write(bufferedImage, ext, file); } |
|