Django+AWS S3分片上传报错:无法获取文件路径导致上传失败
Django + boto3 分片上传到AWS S3 路径错误解决方法
错误原因
你遇到的FileNotFoundError是因为调用s3.upload_file()时传入的file_name_s3是客户端的文件名,但这个文件不存在于服务器本地——浏览器出于安全限制,不会把客户端文件的完整本地路径传给后端,且当前分片逻辑是把每个chunk写到服务器本地文件,而非直接传递完整文件到后端。
修复方案一:基于现有本地合并逻辑上传S3
你的代码已将分片合并到服务器的path = 'media/uploads/video_files/' + fileName_STR路径下,只需将这个本地路径传给s3.upload_file()即可:
修改views.py中的问题代码段:
# 原错误代码 s3.upload_file(file_name_s3 ,bucket,str(fileName_STR)) # 修改后的代码 # 先确保bucket变量已定义(比如从settings读取:bucket = settings.AWS_STORAGE_BUCKET_NAME) # 建议用绝对路径避免问题,比如结合Django的MEDIA_ROOT import os from django.conf import settings local_file_path = os.path.join(settings.MEDIA_ROOT, 'uploads/video_files/', fileName_STR) s3.upload_file(local_file_path, bucket, f'uploads/video_files/{fileName_STR}')
local_file_path是合并后文件在服务器的绝对路径,避免相对路径引发的找不到文件问题- 第三个参数是S3上的对象键(即文件在S3中的存储路径/名称),可根据需求调整
修复方案二:直接用S3 Multipart Upload(更优)
若不想先将文件存在服务器本地,推荐使用boto3的分片上传API直接处理客户端传来的chunk,节省服务器存储空间且更高效:
步骤1:初始化Multipart Upload
当第一个chunk上传时(existingPath == 'null'),创建Multipart Upload并保存upload ID:
# 初始化Multipart Upload response = s3.create_multipart_upload( Bucket=bucket, Key=f'uploads/video_files/{fileName_STR}' ) upload_id = response['UploadId'] # 需在Post模型中新增upload_id字段,用于后续分片上传 FileFolder.upload_id = upload_id
步骤2:上传每个分片
每次收到chunk时,调用upload_part上传:
# 根据分片起始位置计算分片编号(S3要求编号从1开始) part_number = int(nextSlice) // self.max_length + 1 # 需匹配你的分片大小逻辑 # 直接上传chunk内容到S3 response = s3.upload_part( Bucket=bucket, Key=f'uploads/video_files/{fileName_STR}', PartNumber=part_number, UploadId=upload_id, Body=file # 即request.FILES['file'].read()获取的chunk内容 ) # 需在Post模型中新增字段存储分片ETag和编号,比如用JSONField存列表 FileFolder.parts.append({'PartNumber': part_number, 'ETag': response['ETag']})
步骤3:完成Multipart Upload
当最后一个chunk上传完成(end == 1),调用complete_multipart_upload:
# 整理分片信息格式 parts = [{'PartNumber': p['PartNumber'], 'ETag': p['ETag']} for p in FileFolder.parts] # 完成分片上传 s3.complete_multipart_upload( Bucket=bucket, Key=f'uploads/video_files/{fileName_STR}', UploadId=upload_id, MultipartUpload={'Parts': parts} )
额外注意事项
- 浏览器无法获取客户端本地文件的完整路径,这是浏览器安全限制,后端永远无法拿到该路径,只能通过FormData接收文件内容
- 若使用方案一,需确保服务器的
media/uploads/video_files/目录有写入权限 - 分片上传需处理异常,上传失败时要调用
abort_multipart_upload清理S3上的未完成分片
内容的提问来源于stack exchange,提问作者MrLonely
相关产品推荐
相关产品推荐

