验证上传的文件是图像

Verify uploaded file is an image

我将在 .NET Core 1.0.1 的新网站上接受用户上传。但是,我只想允许图像,而不仅仅是任何文件。我如何在 .NET Core 中执行此验证?是否可以不用 System.Drawing,因为它没有实现?

This answer看起来很有前途,但最终还是用了System.Drawing。检查内容类型和扩展名是否足够?


编辑: 接受的答案是我需要的,但我将在这里分享我的实际实现。我在 .NET Core 中执行此操作,但我很确定相同的代码适用于整个框架。

static bool IsJpeg(Stream stream)
{
    using (var br = new BinaryReader(stream))
    {
        var soi = br.ReadUInt16();
        var marker = br.ReadUInt16();
        return soi == 0xd8ff && (marker & 0xe0ff) == 0xe0ff;
    }
}

static bool IsPng(Stream stream)
{
    using (var br = new BinaryReader(stream))
    {
        var soi = br.ReadUInt64();
        return soi == 0x0a1a0a0d474e5089;
    }
}

static bool IsGif(Stream stream)
{
    using (var br = new BinaryReader(stream))
    {
        var soi = br.ReadUInt32();
        var p2 = br.ReadUInt16();

        return soi == 0x38464947 && (p2 == 0x6137 || p2 == 0x6139);
    }
}

仅仅检查文件扩展名是不够的。我可以制作一个 ZIP 文件,然后将扩展名重命名为 .jpg,您会认为它是一个有效文件。

图像格式的开头确实有 "magic bytes",您可以使用它来潜在地识别文件实际上是图像。 This Wikipedia entry here has a list of magic numbers you could check against.

另请注意,内容类型可以被欺骗。

所以你有两件事可以做。原始答案中指定的内容类型,结合检查文件的 "magic numbers"。如果有人真的想上传不是图像的 duff 数据并绕过这两项检查,您可能需要做其他事情。

因此,您可以实施 3 个已知的守卫:

  1. 文件在您的白名单中是否有扩展名? (.jpg/.jpeg/etc...)
  2. 内容类型是否与白名单中的条目匹配? (image/jpeg)
  3. 通过前两个步骤确定文件类型后,幻数是否也匹配?