上传文件验证
上传文件验证分为:1、文件头验证 2、文件类型验证 3、文件后缀验证
- 获取文件上传的二进制数据
# 获取上传文件
file = request.files.get('file')
if file:
# 大文件
if hasattr(file.stream._file, 'peek'):
print(file.stream._file.peek())
# 小文件
elif hasattr(file.stream._file, 'getvalue'):
print(file.stream._file.getvalue())
else:
pass
- 文件头验证
# 类型字典
def typeList():
return {
"FFD8FF": "jpg",
"89504E47": "png",
"255044462D312E": "pdf",
"504B0304": "zip",
"47494638": "gif",
"49492A00": "tif",
"424D": "bmp",
"41433130": "dwg",
"38425053": "psd",
"7B5C727466": "rtf",
"3C3F786D6C": "xml",
"68746D6C3E": "html",
"44656C69766572792D646174653A": "eml",
"CFAD12FEC5FD746F": "dbx",
"2142444E": "pst",
"D0CF11E0": "xls.or.doc",
"5374616E64617264204A": "mdb",
"FF575043": "wpd",
"252150532D41646F6265": "eps.or.ps",
"AC9EBD8F": "qdf",
"E3828596": "pwl",
"52617221": "rar",
"57415645": "wav",
"41564920": "avi",
"2E7261FD": "ram",
"2E524D46": "rm",
"000001BA": "mpg",
"000001B3": "mpg",
"6D6F6F76": "mov",
"3026B2758E66CF11": "asf",
"4D546864": "mid",
"4D5A": "pe"
}
# 字节码转16进制字符串
def bytes2hex(bytes):
num = len(bytes)
hexstr = u""
for i in range(num):
t = u"%x" % bytes[i]
if len(t) % 2:
hexstr += u"0"
hexstr += t
return hexstr.upper()
# 获取文件类型
def filetype(binfile): # binfile 上传文件的二进制数据
tl = typeList()
ftype = 'unknown'
for hcode in tl.keys():
numOfBytes = len(hcode) / 2 # 需要读多少字节
numOfBytes = int(numOfBytes)
k, hbytes = 0, []
for i in binfile:
if k < numOfBytes:
hbytes.append(i)
k += 1
else:
break
hbytes = tuple(hbytes)
f_hcode = bytes2hex(hbytes)
if f_hcode == hcode:
ftype = tl[hcode]
break
# 返回类型字典的value
return ftype
- 文件类型验证
dict = {
"jpg": "jpeg",
"png": "png",
"zip": "zip",
"pdf": "pdf",
"md": "octet-stream"
}
# 检测文件content_type
for type in types:
if dict[type] in file.content_type:
break
else:
pass
- 文件后缀验证
# 检测文件后缀
type = file.filename.split('.')[-1]
if type not in types:
pass