在C#中上传文件时检查文件格式

时间:2017-07-26 05:51:35

标签: asp.net c#-4.0 file-upload

文件上传时我检查了以下内容

   if !(strExtension == ".jpg" || strExtension == ".jpeg" || strExtension == ".pdf" || strExtension == ".png")

   Send Error

这很好用,

但是我有一个问题,如果有人上传xlsx文件,只需将其扩展名更改为jpg,我的上传器就不会阻塞它,文件将被保存,这是一个xlsx文件

如何检查文件来源。没有它的延伸。

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

我有同样的问题。我将分享我的 validator

解决方案
private readonly Dictionary<string, byte[]> _mimeTypes = new Dictionary<string, byte[]>
{
    {"image/jpeg", new byte[] {255, 216, 255}},
    {"image/jpg", new byte[] {255, 216, 255}},
    {"image/pjpeg", new byte[] {255, 216, 255}},
    {"image/apng", new byte[] {137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82}},
    {"image/png", new byte[] {137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82}},
    {"image/bmp", new byte[] {66, 77}},
    {"image/gif", new byte[] {71, 73, 70, 56}},
};

private bool ValidateMimeType(byte[] file, string contentType)
{
    var imageType = _mimeTypes.SingleOrDefault(x => x.Key.Equals(contentType));

    return file.Take(imageType.Value.Length).SequenceEqual(imageType.Value);
}

答案 1 :(得分:0)

修改:只需使用Mime Detective

即可

我使用字节数组序列来确定给定文件的正确MIME类型。仅仅查看文件名的文件扩展名的优点是,如果用户要重命名文件以绕过某些文件类型上载限制,则文件扩展名将无法捕获此信息。另一方面,通过字节数组获取文件签名将阻止这种恶作剧行为的发生。

这是C#中的一个例子:

public class MimeType
{
    private static readonly byte[] BMP = { 66, 77 };
    private static readonly byte[] DOC = { 208, 207, 17, 224, 161, 177, 26, 225 };
    private static readonly byte[] EXE_DLL = { 77, 90 };
    private static readonly byte[] GIF = { 71, 73, 70, 56 };
    private static readonly byte[] ICO = { 0, 0, 1, 0 };
    private static readonly byte[] JPG = { 255, 216, 255 };
    private static readonly byte[] MP3 = { 255, 251, 48 };
    private static readonly byte[] OGG = { 79, 103, 103, 83, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 };
    private static readonly byte[] PDF = { 37, 80, 68, 70, 45, 49, 46 };
    private static readonly byte[] PNG = { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82 };
    private static readonly byte[] RAR = { 82, 97, 114, 33, 26, 7, 0 };
    private static readonly byte[] SWF = { 70, 87, 83 };
    private static readonly byte[] TIFF = { 73, 73, 42, 0 };
    private static readonly byte[] TORRENT = { 100, 56, 58, 97, 110, 110, 111, 117, 110, 99, 101 };
    private static readonly byte[] TTF = { 0, 1, 0, 0, 0 };
    private static readonly byte[] WAV_AVI = { 82, 73, 70, 70 };
    private static readonly byte[] WMV_WMA = { 48, 38, 178, 117, 142, 102, 207, 17, 166, 217, 0, 170, 0, 98, 206, 108 };
    private static readonly byte[] ZIP_DOCX = { 80, 75, 3, 4 };

    public static string GetMimeType(byte[] file, string fileName)
    {

        string mime = "application/octet-stream"; //DEFAULT UNKNOWN MIME TYPE

        //Ensure that the filename isn't empty or null
        if (string.IsNullOrWhiteSpace(fileName))
        {
            return mime;
        }

        //Get the file extension
        string extension = Path.GetExtension(fileName) == null
                               ? string.Empty
                               : Path.GetExtension(fileName).ToUpper();

        //Get the MIME Type
        if (file.Take(2).SequenceEqual(BMP))
        {
            mime = "image/bmp";
        }
        else if (file.Take(8).SequenceEqual(DOC))
        {
            mime = "application/msword";
        }
        else if (file.Take(2).SequenceEqual(EXE_DLL))
        {
            mime = "application/x-msdownload"; //both use same mime type
        }
        else if (file.Take(4).SequenceEqual(GIF))
        {
            mime = "image/gif";
        }
        else if (file.Take(4).SequenceEqual(ICO))
        {
            mime = "image/x-icon";
        }
        else if (file.Take(3).SequenceEqual(JPG))
        {
            mime = "image/jpeg";
        }
        else if (file.Take(3).SequenceEqual(MP3))
        {
            mime = "audio/mpeg";
        }
        else if (file.Take(14).SequenceEqual(OGG))
        {
            if (extension == ".OGX")
            {
                mime = "application/ogg";
            }
            else if (extension == ".OGA")
            {
                mime = "audio/ogg";
            }
            else
            {
                mime = "video/ogg";
            }
        }
        else if (file.Take(7).SequenceEqual(PDF))
        {
            mime = "application/pdf";
        }
        else if (file.Take(16).SequenceEqual(PNG))
        {
            mime = "image/png";
        }
        else if (file.Take(7).SequenceEqual(RAR))
        {
            mime = "application/x-rar-compressed";
        }
        else if (file.Take(3).SequenceEqual(SWF))
        {
            mime = "application/x-shockwave-flash";
        }
        else if (file.Take(4).SequenceEqual(TIFF))
        {
            mime = "image/tiff";
        }
        else if (file.Take(11).SequenceEqual(TORRENT))
        {
            mime = "application/x-bittorrent";
        }
        else if (file.Take(5).SequenceEqual(TTF))
        {
            mime = "application/x-font-ttf";
        }
        else if (file.Take(4).SequenceEqual(WAV_AVI))
        {
            mime = extension == ".AVI" ? "video/x-msvideo" : "audio/x-wav";
        }
        else if (file.Take(16).SequenceEqual(WMV_WMA))
        {
            mime = extension == ".WMA" ? "audio/x-ms-wma" : "video/x-ms-wmv";
        }
        else if (file.Take(4).SequenceEqual(ZIP_DOCX))
        {
            mime = extension == ".DOCX" ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/x-zip-compressed";
        }

        return mime;
    }


}

注意我处理DOCX文件类型的方式不同,因为DOCX实际上只是一个ZIP文件。在这种情况下,我只是在验证它具有该序列后检查文件扩展名。对于某些人来说,这个例子远非完整,但您可以轻松添加自己的。

如果要添加更多MIME类型,可以获取许多不同文件类型from here的字节数组序列。此外,here is another good resource涉及文件签名。

如果所有其他方法都失败了,我会做很多次,我会查找我正在寻找的特定类型的几个文件,并在文件的字节序列中查找模式。最后,这仍然是基本验证,不能用于确定文件类型的100%证明。