在Lambda中获取S3对象MIME类型:仅下载部分文件检测MP4
问题描述
我有一个由S3 PutObject事件触发的Lambda函数,需要验证上传的文件是否为MP4视频文件(文件扩展名不可靠,存在伪造可能)。本地使用filetype库检测MIME类型可行,但不想下载完整的大文件,仅希望下载部分内容到临时存储进行检测。目前的测试代码始终返回None作为MIME类型,怀疑文件保存方式有误,寻求解决帮助。
测试代码:
import boto3 import filetype from time import sleep REGION = 'ap-southeast-1' tmp_path = "path/src/my_file.mp4" start_byte = 0 end_byte = 9000 s3 = boto3.client('s3', region_name=REGION) resp = s3.get_object( Bucket="test", Key="MVI_1494.MP4", Range='bytes={}-{}'.format(start_byte, end_byte) ) # the file object_content = resp['Body'].read() print(type(object_content)) with open(tmp_path, "wb") as binary_file: # Write bytes to file binary_file.write(object_content) sleep(5) kind = filetype.guess_mime(tmp_path) print(kind)
解决方法
你的问题核心出在两个点:
- Lambda临时路径错误:Lambda环境下只有
/tmp/目录是可写的临时存储,你用的相对路径path/src/my_file.mp4无法被正确识别,导致filetype读不到文件。 - 冗余的sleep操作:写入文件后不需要等待,直接检测即可,sleep完全没必要。
另外可以优化检测逻辑,不用写入文件,直接用字节流检测,效率更高。
修正后的代码(写入临时文件版本)
import boto3 import filetype REGION = 'ap-southeast-1' # Lambda临时存储必须用/tmp/开头 tmp_path = "/tmp/my_file.mp4" # 取前10KB足够覆盖MP4的文件签名区域 start_byte = 0 end_byte = 10240 s3 = boto3.client('s3', region_name=REGION) resp = s3.get_object( Bucket="test", Key="MVI_1494.MP4", Range=f'bytes={start_byte}-{end_byte}' ) object_content = resp['Body'].read() with open(tmp_path, "wb") as binary_file: binary_file.write(object_content) kind = filetype.guess_mime(tmp_path) print(kind)
更高效的字节流直接检测版本
import boto3 import filetype REGION = 'ap-southeast-1' start_byte = 0 end_byte = 10240 s3 = boto3.client('s3', region_name=REGION) resp = s3.get_object( Bucket="test", Key="MVI_1494.MP4", Range=f'bytes={start_byte}-{end_byte}' ) object_content = resp['Body'].read() # 直接传入字节数据检测,无需写入文件 kind = filetype.guess_mime(object_content) print(kind)
关键说明
- MP4的文件签名(ftyp盒子)位于文件开头,前10KB足够覆盖所有必要的结构信息,完全不需要下载完整文件。
- Lambda的
/tmp/目录是唯一可写的临时空间,所有临时文件必须放在这里,否则会出现权限或文件找不到的问题。 filetype库支持直接传入字节内容检测,省去IO操作,能提升Lambda的执行速度和资源利用率。
内容的提问来源于stack exchange,提问作者ashraf minhaj
相关产品推荐
相关产品推荐

