识别上传文件的实际类型

本文关键字:类型 文件 识别 | 更新日期: 2023-09-27 18:13:42

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

我正在尝试检测真正的文件类型。对于Office文档(.docx等),我可以将文件作为ZIP文件打开,并查找一个知名的目录(word/用于.docx, xl/用于.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。我有什么选择?

识别上传文件的实际类型

我觉得你想做的事情并不容易,我很抱歉。在以前的Office版本中,您可以通过读取文件的第一个字节并检查那里的签名来区分文件类型。但是在新的xlsxdocx中……格式,它们都共享相同的签名,因为它们是压缩文件,所以它们都以"PK.."开头。你可以这样检查我说的话:

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

无论它是word,excel,powerpoint文件,都会写"PK"。

这里有一个不同文件类型签名的列表。在这里,你会看到所有的办公文档共享相同的内容。

编辑

好了,现在我明白你在做什么了。您希望解压缩办公文件以区分文件类型。你可以这样做:

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中使用压缩命名空间,你必须添加一个对它的引用。我还建议您在调用此方法之前使用我之前的签名解决方案来确定文件是否是压缩文件。

编辑2

如果你需要Net4.0,我建议你使用一个免费的Zip库,如DotNetZip。它很容易使用。从链接中下载zip文件,从zip-v1.9'Release文件夹中解压缩Ionic.Zip.dll文件,在项目中添加对该文件的引用,然后执行以下操作:

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;
}

看一下System.IO.Packaging名称空间,它包含对ZIP文件的支持,但不是ZIP文件的所有特性。