仅根据base64字符串确定文件是zip还是docx/xlsx

问题描述 投票:0回答:1

有什么方法可以仅根据我指定的base64字符串来确定上传的文件是zip文件还是docx/xlsx文件,因为我没有文件扩展名。

到目前为止,我找到了使用像这样的文件扩展名来执行此操作的解决方案

     private static readonly byte[] ZIP_DOCX = { 80, 75, 3, 4 };

     public static string GetMimeType(byte[] file, string fileName)
     {
        string extension = Path.GetExtension(fileName) == null
                           ? string.Empty
                           : Path.GetExtension(fileName).ToUpper();

         if (file.Take(4).SequenceEqual(ZIP_DOCX))
         {
            mime = extension == ".DOCX" ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/x-zip-compressed";
         }
      }

但正如我所说,这个解决方案对我不起作用,因为我没有文件扩展名。有什么想法吗?

c# .net asp.net-core .net-core base64
1个回答
0
投票

听起来很有趣,所以我就玩了一下。这不是基于规范,所以不是超级可靠。我只是提取了一个 Excel 文件和一个 Word 文件,并猜测了可能的识别特征是什么。似乎有效。

public enum FileKind
{
    NotZip,
    OtherZip,
    Xlsx,
    Docx
}

public static class FileKindDecoder
{
    public static FileKind DetermineFileKind(string base64)
    {
        XElement? contentTypesXml;

        var bytes = Convert.FromBase64String(base64);
        using (var stream = new MemoryStream(bytes))
        using (var zip = OpenZip(stream))
        {
            if (zip == null)
                return FileKind.NotZip;

            var contentTypesEntry = zip.GetEntry(@"[Content_Types].xml");
            if (contentTypesEntry == null)
                return FileKind.OtherZip;
            contentTypesXml = ReadXmlFromZip(contentTypesEntry);
        }

        if (contentTypesXml == null)
            return FileKind.OtherZip;

        XNamespace ns = @"http://schemas.openxmlformats.org/package/2006/content-types";
        if (contentTypesXml.Name != ns + "Types")
            return FileKind.OtherZip;

        foreach (var overrideElement in contentTypesXml.Elements(ns + "Override"))
        {
            var contentType = overrideElement.Attribute("ContentType")?.Value;
            if (contentType == null)
                continue;
            if (contentType.Contains("spreadsheetml"))
                return FileKind.Xlsx;
            if (contentType.Contains("wordprocessingml"))
                return FileKind.Docx;
        }

        return FileKind.OtherZip;



        static ZipArchive? OpenZip(Stream stream)
        {
            try
            {
                return new ZipArchive(stream);
            }
            catch (InvalidDataException)
            {
                return null;
            }
        }

        static XElement? ReadXmlFromZip(ZipArchiveEntry entry)
        {
            using var stream = entry.Open();
            try
            {
                return XElement.Load(stream);
            }
            catch (XmlException)
            {
                return null;
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.