文件上傳在Struts的Action檢測文件類型

在頁面有文件上傳的表單。(只能上傳jpg/png文件)
檢測根據文件的文件頭(不是後綴名)判斷文件類型

一、Struts2文件上傳 
實現規則:
(1)在JSP中設定表單控件<s:file name="upload" label="上傳"/>
(2)在Action中定義屬性:(注意命名方式是固定的)
private File upload;        //包含文件內容
private String uploadFileName;    //上傳文件的名稱;
private String uploadContentType;    //上傳文件的MIME類型;
這些屬性都會隨着文件的上傳自動賦值;
(3)在execute()中完成寫入磁盤功能;

1、Action代碼:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class TestAction extends BaseAction implements SessionAware, ServletRequestAware, ServletResponseAware
{
	private final static int FILEMAXSIZE = 10 * 1024 * 1024;
	private File testfile;
	private User user;

	public String execute()throws Exception{
	/*

	execute代碼裏面會調用treatFile(testfile)判斷,上傳文件的類型
	
	*/
	}

	/*檢測爲jpg/png類型返回null,若不是怎返回錯誤信息*/
	private String treatFile(File file)
	{
		if (file == null){
			return "圖片文件爲空";
		}
		if (file.length() > FILEMAXSIZE)
			return "圖片文件過大";

		InputStream is = null;
		OutputStream os = null;
		try
		{
			String ext;
			is = new FileInputStream(file);
			//檢測文件類型
			FileType fileType = FileTypeJudge.getType(is);
			if (FileType.JPEG.equals(fileType))
				ext = ".jpg";
			else if (FileType.PNG.equals(fileType))
				ext = ".png";
			else
				return "圖片文件不是JPG/PNG格式";
			
			is.close();
			
			//文件上傳部分
			String root = ServletActionContext.getServletContext()
					.getRealPath("/userimages");
			String fileName = user.getId() + "_" + System.currentTimeMillis() + ext;
			is = new FileInputStream(file);
			os = new FileOutputStream(new File(root, fileName));
			byte[] buffer = new byte[1024];
			int length = 0;
			while (-1 != (length = is.read(buffer, 0, buffer.length)))
				os.write(buffer, 0, length);

			return null;
		}
		catch (IOException e)
		{
			e.printStackTrace();
			return "圖片文件處理時發生IO錯誤";
		}
		finally
		{
			if (is != null)
				try
				{
					is.close();
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			if (os != null)
				try
				{
					os.close();
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
		}
	
	}


	public void setTestfile(File testfile)
	{
		this.testfile = testfile;
	}
	public File getTestfile()
	{
		return testfile;
	}
	public User getUser()
	{
		return user;
	}
	public void setUser(User user)
	{
		this.user = user;
	}
}


2、文件類型枚舉類 ,枚舉類有一個values()方法,這個方法可以將枚舉類轉換成一個枚舉類型的數組,轉換成數組之後我們就可以通過下標來訪問我們的枚舉類中的值。

package org.util;
/**
 * 文件類型枚舉
 */
public enum FileType
{
	/**
	 * JEPG.
	 */
	JPEG("FFD8FF"),

	/**
	 * PNG.
	 */
	PNG("89504E47"),

	/**
	 * GIF.
	 */
	GIF("47494638"),

	/**
	 * TIFF.
	 */
	TIFF("49492A00"),

	/**
	 * Windows Bitmap.
	 */
	BMP("424D"),

	/**
	 * CAD.
	 */
	DWG("41433130"),

	/**
	 * Adobe Photoshop.
	 */
	PSD("38425053"),

	/**
	 * Rich Text Format.
	 */
	RTF("7B5C727466"),

	/**
	 * XML.
	 */
	XML("3C3F786D6C"),

	/**
	 * HTML.
	 */
	HTML("68746D6C3E"),

	/**
	 * CSS.
	 */
	CSS("48544D4C207B0D0A0942"),

	/**
	 * JS.
	 */
	JS("696B2E71623D696B2E71"),

	/**
	 * Email [thorough only].
	 */
	EML("44656C69766572792D646174653A"),

	/**
	 * Outlook Express.
	 */
	DBX("CFAD12FEC5FD746F"),

	/**
	 * Outlook (pst).
	 */
	PST("2142444E"),

	/**
	 * MS Word/Excel.
	 */
	XLS_DOC("D0CF11E0"), XLSX_DOCX("504B030414000600080000002100"),

	/**
	 * Visio
	 */
	VSD("d0cf11e0a1b11ae10000"),

	/**
	 * MS Access.
	 */
	MDB("5374616E64617264204A"),

	/**
	 * WPS文字wps、表格et、演示dps都是一樣的
	 */
	WPS("d0cf11e0a1b11ae10000"),

	/**
	 * torrent
	 */
	TORRENT("6431303A637265617465"),

	/**
	 * WordPerfect.
	 */
	WPD("FF575043"),

	/**
	 * Postscript.
	 */
	EPS("252150532D41646F6265"),

	/**
	 * Adobe Acrobat.
	 */
	PDF("255044462D312E"),

	/**
	 * Quicken.
	 */
	QDF("AC9EBD8F"),

	/**
	 * Windows Password.
	 */
	PWL("E3828596"),

	/**
	 * ZIP Archive.
	 */
	ZIP("504B0304"),

	/**
	 * RAR Archive.
	 */
	RAR("52617221"),

	/**
	 * JSP Archive.
	 */
	JSP("3C2540207061676520"),

	/**
	 * JAVA Archive.
	 */
	JAVA("7061636B61676520"),

	/**
	 * CLASS Archive.
	 */
	CLASS("CAFEBABE0000002E00"),

	/**
	 * JAR Archive.
	 */
	JAR("504B03040A000000"),

	/**
	 * MF Archive.
	 */
	MF("4D616E69666573742D56"),

	/**
	 * EXE Archive.
	 */
	EXE("4D5A9000030000000400"),

	/**
	 * CHM Archive.
	 */
	CHM("49545346030000006000"),

	/* 
	 * INI("235468697320636F6E66"), SQL("494E5345525420494E54"), BAT( 
	 * "406563686F206f66660D"), GZ("1F8B0800000000000000"), PROPERTIES( 
	 * "6C6F67346A2E726F6F74"), MXP( 
	 * "04000000010000001300"), 
	 */

	/**
	 * Wave.
	 */
	WAV("57415645"),

	/**
	 * AVI.
	 */
	AVI("41564920"),

	/**
	 * Real Audio.
	 */
	RAM("2E7261FD"),

	/**
	 * Real Media.
	 */
	RM("2E524D46"),

	/**
	 * MPEG (mpg).
	 */
	MPG("000001BA"),

	/**
	 * Quicktime.
	 */
	MOV("6D6F6F76"),

	/**
	 * Windows Media.
	 */
	ASF("3026B2758E66CF11"),

	/**
	 * MIDI.
	 */
	MID("4D546864"),

	/**
	 * MP4.
	 */
	MP4("00000020667479706d70"),

	/**
	 * MP3.
	 */
	MP3("49443303000000002176"),

	/**
	 * FLV.
	 */
	FLV("464C5601050000000900");

	private String value = "";

	/**
	 * Constructor.
	 * 
	 * @param type
	 */
	private FileType(String value)
	{
		this.value = value;
	}

	public String getValue()
	{
		return value;
	}

	public void setValue(String value)
	{
		this.value = value;
	}
}


3、判斷文件真實類型FileTypeJudge.getType(is)

package org.util;

import java.io.IOException;
import java.io.InputStream;

/**
 * 文件類型判斷類
 */
public final class FileTypeJudge
{
	private FileTypeJudge()
	{
	}

	/**
	 * 將文件頭轉換成16進制字符串
	 * 
	 * @param 原生byte
	 * @return 16進制字符串
	 */
	private 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();
	}

	/**
	 * 得到文件頭字節塊
	 * 
	 * @param is
	 *            InputStream 文件輸入流
	 * @return 16進制文件頭
	 * @throws IOException
	 */
	private static String getFileHead(InputStream is)
	{

		byte[] b = new byte[28];

		try
		{
			is.read(b, 0, 28);
			return bytesToHexString(b);
		}
		catch (IOException e)
		{
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 判斷文件類型
	 * 
	 * @param is
	 *            InputStream 文件輸入流
	 * @return FileType 文件類型
	 */
	public static FileType getType(InputStream is) throws IOException
	{

		String fileHead = getFileHead(is);

		if (fileHead == null || fileHead.length() == 0)
		{
			return null;
		}

		fileHead = fileHead.toUpperCase();

		FileType[] fileTypes = FileType.values();

		for (FileType type : fileTypes)
		{
			if (fileHead.startsWith(type.getValue()))
			{
				return type;
			}
		}

		return null;
	}

	/**
	 * 得到文件類型分類碼
	 * 
	 * @param value
	 *            FileType 文件類型
	 * @return Integer 文件類型分類碼(圖片:1,文檔:2,視頻:3,種子:4,音樂:5,其他:7)
	 */
	public static Integer isFileType(FileType value)
	{
		Integer type = 7;// 其他
		// 圖片
		FileType[] pics = { FileType.JPEG, FileType.PNG, FileType.GIF,
				FileType.TIFF, FileType.BMP, FileType.DWG, FileType.PSD };

		FileType[] docs = { FileType.RTF, FileType.XML, FileType.HTML,
				FileType.CSS, FileType.JS, FileType.EML, FileType.DBX,
				FileType.PST, FileType.XLS_DOC, FileType.XLSX_DOCX,
				FileType.VSD, FileType.MDB, FileType.WPS, FileType.WPD,
				FileType.EPS, FileType.PDF, FileType.QDF, FileType.PWL,
				FileType.ZIP, FileType.RAR, FileType.JSP, FileType.JAVA,
				FileType.CLASS, FileType.JAR, FileType.MF, FileType.EXE,
				FileType.CHM };

		FileType[] videos = { FileType.AVI, FileType.RAM, FileType.RM,
				FileType.MPG, FileType.MOV, FileType.ASF, FileType.MP4,
				FileType.FLV, FileType.MID };

		FileType[] tottents = { FileType.TORRENT };

		FileType[] audios = { FileType.WAV, FileType.MP3 };

		FileType[] others = {};

		// 圖片
		for (FileType fileType : pics)
		{
			if (fileType.equals(value))
			{
				type = 1;
			}
		}
		// 文檔
		for (FileType fileType : docs)
		{
			if (fileType.equals(value))
			{
				type = 2;
			}
		}
		// 視頻
		for (FileType fileType : videos)
		{
			if (fileType.equals(value))
			{
				type = 3;
			}
		}
		// 種子
		for (FileType fileType : tottents)
		{
			if (fileType.equals(value))
			{
				type = 4;
			}
		}
		// 音樂
		for (FileType fileType : audios)
		{
			if (fileType.equals(value))
			{
				type = 5;
			}
		}
		return type;
	}

	public static void main(String args[]) throws Exception
	{
		// System.out.println(FileTypeJudge.getType(new FileInputStream("")));
		for (FileType type : FileType.values())
		{
			System.out.println(type + "\t" + type.getValue());
		}
	}
}




--------------------------------------------------------------------------------------------
參考http://www.360doc.com/content/14/1029/16/17799864_420904491.shtml


《File Header文件頭》
另外還有一些重要的文件,沒有固定的文件頭,如下:


TXT 沒固定文件頭定義
TMP 沒固定文件頭定義
INI 沒固定文件頭定義
BIN 沒固定文件頭定義
DBF 沒固定文件頭定義
C 沒沒固定文件頭定義
CPP 沒固定文件頭定義
H 沒固定文件頭定義
BAT 沒固定文件頭定義


還有一些不同的文件有相同的文件頭,最典型的就是下面:


4D5A90 EXE
4D5A90 dll
4D5A90 OCX
4D5A90 OLB
4D5A90 IMM
4D5A90 IME


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章