如何检查文件是否是有效图像?

时间:2014-09-21 12:52:18

标签: go mime

我正在构建一个Web应用程序。

在其中一个页面上有一个上传表单,用户可以在其中上传文件。上传完成后,我想检查服务器上传的文件是否为图像。

是否可以在简单的文件扩展名检查之外检查(即不假设*.png文件名实际上是PNG图像)?

例如,如果我编辑JPEG图像在随机位置添加/编辑一个字节以生成无效的JPEG文件,我想检测它不再是JPEG图像。我曾经使用过GD库,通过PHP做过类似的事情。

我想知道是否可以使用Go?

3 个答案:

答案 0 :(得分:16)

The http package can do this for you:

func DetectContentType(data []byte) string

DetectContentType implements the algorithm described at http://mimesniff.spec.whatwg.org/ to determine the Content-Type of the given data. It considers at most the first 512 bytes of data. DetectContentType always returns a valid MIME type: if it cannot determine a more specific one, it returns "application/octet-stream".

Code: https://golang.org/src/net/http/sniff.go

答案 1 :(得分:14)

DetectContentType比手动魔术数字检查更好。用法很简单:

clientFile, _, _ := r.FormFile("img") // or get your file from a file system
defer clientFile.Close()
buff := make([]byte, 512) // docs tell that it take only first 512 bytes into consideration
if _, err = clientFile.Read(buff); err != nil {
     fmt.Println(err) // do something with that error
     return
}

fmt.Println(http.DetectContentType(buff)) // do something based on your detection.

使用此方法您需要知道您仍然无法保证拥有正确的文件。所以我建议对该文件进行一些图像处理(比如调整它以确保它确实是一个图像)。

答案 2 :(得分:10)

通常做的是检查文件是否具有所需图像文件格式的magic number权限。虽然这个测试不是非常准确,但通常都足够好。您可以使用以下代码:

package foo

import "strings"

// image formats and magic numbers
var magicTable = map[string]string{
    "\xff\xd8\xff":      "image/jpeg",
    "\x89PNG\r\n\x1a\n": "image/png",
    "GIF87a":            "image/gif",
    "GIF89a":            "image/gif",
}

// mimeFromIncipit returns the mime type of an image file from its first few
// bytes or the empty string if the file does not look like a known file type
func mimeFromIncipit(incipit []byte) string {
    incipitStr := []byte(incipit)
    for magic, mime := range magicTable {
        if strings.HasPrefix(incipitStr, magic) {
            return mime
        }
    }

    return ""
}