2014-09-21 2 views
12

웹 응용 프로그램을 구축 중입니다.파일이 유효한 이미지인지 확인하는 방법은 무엇입니까?

페이지 중 하나에 사용자가 파일을 업로드 할 수있는 업로드 양식이 있습니다. 업로드가 완료되면 업로드 된 파일이 이미지인지 서버에 확인하고 싶습니다.

간단한 파일 확장자 확인 (즉, *.png 파일 이름이 실제로 PNG 이미지라고 가정하지 않고)을 검사 할 수 있습니까?

예를 들어 잘못된 JPEG 파일을 만들기 위해 임의의 위치에서 바이트를 추가/편집하는 JPEG 이미지를 편집하는 경우 더 이상 JPEG 이미지가 아닌 것을 감지하고 싶습니다. 이전에는 GD 라이브러리를 사용하여 PHP를 통해 이러한 유형의 작업을 수행했습니다.

이동과 관련이 있는지 알고 싶습니다.

+2

원하는 것은 항상 가능한 것은 아닙니다. 임의의 문자를 이미지 파일의 중간에 삽입하면 이미지가 손상되지만 일반적으로 이미지는 멈추지 않습니다. – fuz

답변

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 "" 
} 
+0

헤더를 검사하는 것이 충분하지 않은 경우 모든 관련 이미지 패키지 ('image/png','image/gif','image/jpeg','golang.org/x/image/bmp')를로드 할 수 있습니다. , etc.)'image.DecodeConfig' 또는 ['image.Decode'] (https://golang.org/pkg/image/#Decode)를 사용하여 오류를 확인하십시오. 악성 데이터가 디코더를 대상으로하는 버그를 조심하십시오. –

+0

@DaveC 위의 내 자신의 의견에서 말했듯이, 이미지의 디코딩은 이미지 중간의 임의의 바이트를 변경하면 일반적으로 이미지 파일이 "손상된"것으로 인식되지 않으므로 문제를 해결하지 못합니다. – fuz

+3

참으로! 원본의 안전한 해시가 없으면 양성 수정을 감지 할 수 없습니다. 그러나 원하는 경우 * (답변에서 말한 것처럼 일반적으로 헤더만으로도 충분 함) 전체 데이터가 유효한 이미지를 나타내는 지 확인할 수 있습니다 (관련 이미지 디코딩이 부패 ​​된 입력에 대한 오류를보고 한 경우 손상된 데이터를 반환하는 것으로 가정 함). 이미지 오류가없는, 예를 들어 그냥 원시 픽셀 데이터를 포함하는 간단한 이미지 형식 괜찮아 바이트의 정확한 숫자가 존재하는 동안 나는 JPEG 디코더가 더 압축 된 입력에 대해 까다 롭습 같은 희망을 줄 것이다. –

9

는 HTTP 패키지는 당신을 위해이 작업을 수행 할 수 있습니다

func DetectContentType(data []byte) string 

DetectContentType가 주어진 의 콘텐츠 형식을 결정하기 위해 http://mimesniff.spec.whatwg.org/에 설명 된 알고리즘을 구현 데이터. 기껏해야 512 바이트의 데이터를 고려합니다. DetectContentType은 항상 유효한 MIME 형식을 반환합니다. 이 더 구체적인 MIME 형식을 결정할 수 없으면 "application/octet-stream"을 반환합니다.

코드 : https://golang.org/src/net/http/sniff.go

+0

좋습니다! 고맙습니다. – Deleplace

9

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. 

이 방법을 사용하면 올바른 파일을 사용할 수 없다는 것을 알아야합니다. 그래서 나는이 파일로 이미지 조작을하는 것이 좋습니다. (이미지 크기를 조정하는 것과 같습니다.)

관련 문제