平时在上传文件文件时,只允许上传jpg,gif,png等后缀的图片文件,这个可以根据文件后缀名来过滤。但是如果用户修改了后缀名来欺骗系统的话又该怎么解决?比如a.txt格式的改成a.jpg,我现在的程序就无法识别了,虽然在后台可以弹出错误,但这个错误已经不是FS上定义的错误了。
解决:
在网上查了好多资料,大部分都是通过将文件读成二进制流,取前两个字节判断,比如.jpg的是255216.代码如下:
public static FileExtension CheckTextFile(string fileName) { FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); System.IO.BinaryReader br = new System.IO.BinaryReader(fs); string fileType = string.Empty; ; try { byte data = br.ReadByte(); fileType += data.ToString(); data = br.ReadByte(); fileType += data.ToString(); FileExtension extension; try { extension = (FileExtension)Enum.Parse(typeof(FileExtension), fileType); } catch {
extension=FileExtension.VALIDFILE } return extension; } catch (Exception ex) { throw ex; } finally { if (fs != null) { fs.Close(); br.Close(); } } } } public enum FileExtension { JPG = 255216, GIF = 7173, PNG = 13780, SWF = 6787, RAR = 8297, ZIP = 8075, _7Z = 55122, VALIDFILE=9999999 // 255216 jpg;
// 7173 gif;
// 6677 bmp,
// 13780 png;
// 6787 swf
// 7790 exe dll,
// 8297 rar
// 8075 zip
// 55122 7z
// 6063 xml
// 6033 html
// 239187 aspx
// 117115 cs
// 119105 js
// 102100 txt
// 255254 sql
}
经过测试,可以很好的判断.jpg、.gif格式的文件.
然而对于.txt文件却不是102100,每个.txt返回的值也不一样。显然,这个方法不能满足我的需要。
后来看到一个delphi写的,这里有一个很简单的方法:把给定的那个文件看作是无类型的二进制文件,然后顺序地读出这个文件的每一个字节,如果文件里有一个字节的值等于0,那么这个文件就不是文本文件;反之,如果这个文件中没有一个字节的值是0的话,就可以判定这个文件是文本文件了。这是原理,下面看看在Delphi 中怎样编程来实现它--
function IsTextFile(FileName:string):boolean; var Fs:TFileStream; i,size:integer; IsTextFile:boolean; ByteData:Byte; begin if FileExists(FileName) then begin Fs:=TFileStream.Create(FileName,fmOpenRead); IsTextFile:=true; i:=0; size:=Fs.Size; While (i<size) and IsTextFile do begin Fs.Read(ByteData,1); IsTextFile:=ByteData<>0; inc(i) end; Fs.Free; Result:=IsTextFile end else Result:=false end;
我把它翻译成C#代码后是这样的:
/// <summary> /// Checks the file is textfile or not. /// </summary> /// <param name="fileName">Name of the file.</param> /// <returns></returns> public static bool CheckIsTextFile(string fileName) { FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); bool isTextFile=true; try { int i = 0; int length = (int)fs.Length; byte data; while (i < length && isTextFile) { data = (byte)fs.ReadByte(); isTextFile = (data != 0); i++; } return isTextFile; } catch (Exception ex) { throw ex; } finally { if (fs != null) { fs.Close(); } } }
后来经过测试,满足了我的需求。
附测试代码:
bool isTextFile = Utility.CheckIsTextFile(this.openFile.FileName); if (isTextFile) { this.richTxtContent.AppendText(openFile.FileName + "是文本文件"); } else { this.richTxtContent.AppendText(openFile.FileName + "不是文本文件!"); }
|
请发表评论