我正在构建一个Web应用程序。
在其中一个页面上有一个上传表单,用户可以在其中上传文件。上传完成后,我想检查服务器上传的文件是否为图像。
是否可以在简单的文件扩展名检查之外检查(即不假设*.png
文件名实际上是PNG图像)?
例如,如果我编辑JPEG图像在随机位置添加/编辑一个字节以生成无效的JPEG文件,我想检测它不再是JPEG图像。我曾经使用过GD库,通过PHP做过类似的事情。
我想知道是否可以使用Go?
答案 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".
答案 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 ""
}