验证.vhd文件实际上是vhd

时间:2019-01-21 17:42:07

标签: c# asp.net validation vhd

用户可以将vhd文件上传到我的服务器。我想验证它们上载的文件,并确保它们实际上是有效的vhd文件,而不是用.vhd文件扩展名或其他名称重新命名的jpeg。是否可以执行此操作?

1 个答案:

答案 0 :(得分:1)

https://www.garykessler.net/library/file_sigs.html(按Ctrl + F,然后输入VHD)

VHD文件的前8个字节似乎如下:63 6F 6E 65 63 74 69 78(ASCII中的conectix。)

如@jdweng在注释部分中所建议,您也许可以使用BinaryReader来读取前8个字节并将其与上面的值进行比较,以确定该文件是否为VHD文件。

编辑:不起作用,正在寻找其他解决方案。

编辑2:实际上,文件中确实存在文本conectix,但它不在文件的开头;文本位于第[the end of the file] - 0x200个字节。现在要对其进行测试。仅供参考,该文件是使用Windows 10上的磁盘管理工具生成的。

编辑3:

private static bool IsVhd(string path)
{
    byte[] vhdHeader = { 0x63, 0x6F, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x78 };
    byte[] header;

    FileInfo file = new FileInfo(path);
    long length = file.Length;

    using (BinaryReader br = new BinaryReader(file.OpenRead()))
    {
        br.BaseStream.Position = length - 0x200; //Where the "conectix" is located at
        header = br.ReadBytes(8);
    }

    return vhdHeader.SequenceEqual(header);
}

我相信这会做到的。

编辑4:

private static bool IsVhd(string path)
{
    Span<byte> vhdHeader = stackalloc byte[] { 0x63, 0x6F, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x78 };
    Span<byte> header = stackalloc byte[8];

    FileInfo file = new FileInfo(path);
    long length = file.Length;

    using (BinaryReader br = new BinaryReader(file.OpenRead()))
    {
        br.BaseStream.Position = length - 0x200; //Where the "conectix" is located at
        br.Read(header);
    }

    return vhdHeader.SequenceEqual(header);
}

未分配版本,如果您使用的是.NET Core。 (需要C#7.3)

编辑5:

private static bool IsVhd(string path)
{
    Span<byte> vhdHeader = stackalloc byte[] { 0x63, 0x6F, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x78 };
    Span<byte> header = stackalloc byte[8];

    FileInfo file = new FileInfo(path);
    long length = file.Length;

    using (BinaryReader br = new BinaryReader(file.OpenRead()))
    {
        br.BaseStream.Position = length - 0x200; //Where the "conectix" is located at
        for (int i = 0; i < 8; i++)
            header[i] = br.ReadByte();
    }

    return vhdHeader.SequenceEqual(header);
}

相同,但适用于.NET Frameworks(由于优化,理想情况下为4.7.1版;还需要System.Memory NuGet程序包。C#7.3)

编辑6: According to the specs,似乎“硬盘页脚”位于最后的512(如果在MS Virtual PC 2004之前创建,则为511)字节。

Note: Versions previous to Microsoft Virtual PC 2004 create disk images that have a 511-byte disk footer. So the hard disk footer can exist in the last 511 or 512 bytes of the file that holds the hard disk image.

Hard Disk Footer Field Descriptions
The following provides detailed definitions of the hard disk footer fields.
Cookie
Cookies are used to uniquely identify the original creator of the hard disk image. The values are case-sensitive.
Microsoft uses the “conectix” string to identify this file as a hard disk image created by Microsoft Virtual Server, Virtual PC, and predecessor products. The cookie is stored as an eight-character ASCII string with the “c” in the first byte, the “o” in the second byte, and so on.

如果文件大小小于512字节,则我以前编写的代码将不起作用。我已修复它,因此它现在也可以处理511字节页脚的文件。此外,我添加了一些注释以帮助维护。

/// <summary>
/// Determines whether the file indicated by the given path is a valid Virtual Hard Disk (.vhd) file.
/// </summary>
/// <param name="path">The path to the .vhd file to check.</param>
/// <returns>Whether the file is a valid vhd file or not.</returns>
//https://www.microsoft.com/en-us/download/details.aspx?id=23850
//See 'Hard Disk Footer Format'
//ASCII string "conectix" (63 6F 6E 65 63 74 69 78) is stored at the last 512 (511 if created on legacy platforms) bytes of the file
private static bool IsVhd(string path)
{
    if (path is null) throw new ArgumentNullException(nameof(path));

    Span<byte> vhdFooterCookie = stackalloc byte[] { 0x63, 0x6F, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x78 };
    Span<byte> cookie = stackalloc byte[9];

    FileInfo file = new FileInfo(path);
    long length = file.Length;
    if (length < 511) return false; //Cannot be smaller than 512 bytes

    using (BinaryReader br = new BinaryReader(file.OpenRead()))
    {
        br.BaseStream.Position = length - 0x200; //Where the footer starts from
#if NETCOREAPP
        br.Read(cookie);
#else
        for (int i = 0; i < 9; i++)
            cookie[i] = br.ReadByte();
#endif
    }

    //SequenceEqual returns false if length is not equal, therefore we slice it to match
    return vhdFooterCookie.SequenceEqual(cookie.Slice(0, 8)) 
           || vhdFooterCookie.SequenceEqual(cookie.Slice(1)); //If created on legacy platform
}

有一些条件编译位,但是我相信您可以删除不必要的位以符合您的需求。

相关问题