识别上传文件的实际类型?

时间:2016-10-18 09:08:06

标签: c#

我允许用户将某些文件上传到我的服务器,我想验证他们没有更改文件扩展名。例如,用户可能会将.bat文件重命名为.xlsx,然后将其上传。

我正在尝试检测真实的文件类型。对于Office文档(.docx等),我可以将文件作为ZIP文件打开,并查找知名目录(word/ .docxxl/ .xlsx等。)。

我正在使用以下代码:

private static FileType CheckForCompressFile(FileType type, string fileFullName)
{
    FileType result = null;
    using (var zipFile = ZipFile.OpenRead(fileFullName))
    {
        if (zipFile.Entries.Any(e => e.FullName.StartsWith("word/")))
            result = WORDX;
        else if (zipFile.Entries.Any(e => e.FullName.StartsWith("xl/")))
            result = EXCELX;
        else if (zipFile.Entries.Any(e => e.FullName.StartsWith("ppt/")))
             result = PPTX;
         else if (zipFile.Entries.Any(e => e.FullName.StartsWith("sbt/")))
             result = JAR;
         else
             result = CheckForOdtAndOds(result, zipFile);
    }
    return result;
  }

System.IO中的ZIP支持仅在.NET 4.5中可用,我需要使用.NET 4.0。我有什么选择?

2 个答案:

答案 0 :(得分:0)

查看System.IO.Packaging命名空间,该命名空间包含对ZIP文件的支持,但不包含ZIP文件的所有功能。

答案 1 :(得分:0)

我认为你要做的事情并不容易,对不起。在以前的Office版本中,您可以通过读取文件的第一个字节并检查其中的签名来区分文件类型。但是在新的xlsxdocx ...格式中,它们都共享相同的签名,因为它们是压缩文件,所以它们都以'PK ..'开头。你可以用这种方式检查我的意思:

byte[] fileBytes = File.ReadAllBytes(@"file.docx");
string signature = ((char)fileBytes[0]).ToString() + ((char)fileBytes[1]).ToString();
Console.WriteLine(signature);

这会写'PK',无论是一个单词,excel,powerpoint文件......

Here您有不同文件类型签名的列表。在那里你会看到所有的办公文档都是一样的。

修改

好的,现在我明白你在做什么。您想要解压缩office文件以区分文件类型。你可以这样做:

private static FileType CheckForCompressFile(FileType type, string fileFullName)
{
   FileType result = null;
   FileStream fileBytes = new FileStream(fileFullName, FileMode.Open);
        using (System.IO.Compression.ZipArchive zipFile = new System.IO.Compression.ZipArchive(fileBytes))
        {
            if (zipFile.Entries.Any(e => e.FullName.StartsWith("word/")))
                result = WORDX;
            else if (zipFile.Entries.Any(e => e.FullName.StartsWith("xl/")))
                result = EXCELX;
            else if (zipFile.Entries.Any(e => e.FullName.StartsWith("ppt/")))
                result = PPTX;
            else if (zipFile.Entries.Any(e => e.FullName.StartsWith("sbt/")))
                result = JAR;
            else
                result = CheckForOdtAndOds(result, zipFile);
        }
        return result;
    }

如果要在Net 4.0中使用它,则必须添加对Compression namespace的引用。我还建议您在调用此方法之前使用我以前的签名解决方案来确定文件是否为压缩文件。

修改2

如果您需要Net4.0,我建议您使用免费的Zip库,DotNetZip。它易于使用。只需从链接下载zip,从Ionic.Zip.dll文件夹解压缩文件zip-v1.9\Release,在您的proyect中添加对此文件的引用,然后执行此操作:

private static FileType CheckForCompressFile(string fileFullName)
{
    FileType result = null;

    using (Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile(fileFullName))
    {
        if (zipFile.Entries.Any(e => e.FileName.StartsWith("word/")))
            result = WORDX;
        else if (zipFile.Entries.Any(e => e.FileName.StartsWith("xl/")))
            result = EXCELX;
        else if (zipFile.Entries.Any(e => e.FileName.StartsWith("ppt/")))
            result = PPTX;
        else if (zipFile.Entries.Any(e => e.FileName.StartsWith("sbt/")))
            result = JAR;
        else
            result = CheckForOdtAndOds(result, zipFile);
    }
    return result;
}