Django+AWS S3分片上传报错:No such file or directory
问题描述
尝试了所有方法都没用,大概知道问题出在哪但不知道怎么修复。用分片上传方案绕过Cloudflare的100MB文件上传限制,执行代码时出现文件找不到的错误,目前只需要把视频保存到AWS S3,图片逻辑类似。
报错信息
with open(object_name, 'rb') as destination:
FileNotFoundError: [Errno 2] No such file or directory: '/home/mrlonely/Desktop/lumen/lumen/Bones - TheArtOfCremation-tqSpI1Jm0YE-1080p.mp4'
相关代码(create_post视图函数)
def create_post(request): # s3_client=boto3.client('s3') s3 = boto3.client('s3', region_name=settings.AWS_S3_REGION_NAME, aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY) categories_1 = Category.objects.all() if request.method == 'POST': file = request.FILES['file'].read() file_name_s3 = request.POST['filename'] fileName= request.POST['filename'].replace(' ', '') fileName_STR = re.sub("[^A-Z]", "", fileName,0,re.IGNORECASE) + '.mp4' existingPath = request.POST['existingPath'] end = request.POST['end'] image = request.FILES.get('image', False) imageName = request.FILES.get('imagename', False) if image != False: image = request.FILES['image'].read() imageName= request.POST['imagename'].replace(' ', '') else: pass title = request.POST['title'] tags = request.POST['tags'] categories = parse_ids(request.POST['categories']) description = request.POST['description'] nextSlice = request.POST['nextSlice'] if file=="" or fileName_STR=="" or existingPath=="" or end=="" or nextSlice=="": res = JsonResponse({'data':'Invalid Request'}) return res else: if existingPath == 'null': path = 'media/uploads/video_files/' + fileName if image != False: with open(path, 'wb+') as destination: destination.write(file) imagePath = 'media/thumbnail/' + imageName else: pass if image: with open(imagePath, 'wb+') as destination: destination.write(image) else: pass object_name = Path.joinpath(BASE_DIR, file_name_s3) # handles the upload................... path = 'media/uploads/video_files/' + fileName_STR with open(object_name, 'rb') as destination: s3_client.upload_file(object_name ,bucket,fileName_STR) # ............................................ FileFolder = Post() FileFolder.video = 'uploads/video_files/'+fileName_STR FileFolder.existingPath = fileName_STR FileFolder.eof = end FileFolder.title = title FileFolder.author = request.user FileFolder.description = description if image == False: FileFolder.thumbnail = None else: FileFolder.thumbnail = 'thumbnail/' + imageName FileFolder.approved = True FileFolder.save() tag_list = taggit.utils._parse_tags(tags) FileFolder.tags.add(*tag_list) categories_post = Category.objects.filter(id__in=categories) if categories_post: for category in categories_post: FileFolder.categories.add(category) if int(end): res = JsonResponse({'data':'Uploaded Successfully','existingPath': fileName}) else: res = JsonResponse({'existingPath': fileName_STR}) return res else: path = 'media/uploads/video_files/' + existingPath model_id = Post.objects.get(existingPath=existingPath) if model_id.title == title: if not model_id.eof: with open(path, 'ab+') as destination: destination.write(file) if int(end): model_id.eof = int(end) model_id.save() res = JsonResponse({'data':'Uploaded Successfully','existingPath':model_id.existingPath}) else: res = JsonResponse({'existingPath':model_id.existingPath}) return res else: res = JsonResponse({'data':'EOF found. Invalid request'}) return res else: res = JsonResponse({'data':'No such file exists in the existingPath'}) return res return render(request, 'main/create_post.html', {'categories': categories_1})
问题根源与修复方案
1. 错误核心
代码中文件写入路径和读取路径不匹配:
- 分片内容被写入到
media/uploads/video_files/下的文件 - 上传S3时却尝试读取
BASE_DIR根目录下的file_name_s3文件,这个文件根本不存在,自然报找不到的错误 - 另外代码里初始化了
s3客户端,但上传时用了未定义的s3_client,变量名也不一致
2. 修复步骤
(1)统一文件路径
把分片写入和S3读取的路径统一,确保操作的是同一个文件:
# 替换existingPath == 'null'分支里的路径相关代码 if existingPath == 'null': # 定义统一的本地视频存储路径 local_video_dir = Path.joinpath(BASE_DIR, 'media', 'uploads', 'video_files') # 确保目录存在,避免因目录缺失报错 local_video_dir.mkdir(parents=True, exist_ok=True) local_video_path = local_video_dir / fileName_STR # 写入当前分片内容 with open(local_video_path, 'wb+') as destination: destination.write(file) # 图片处理逻辑(略,同样要确保目录存在) if image: local_image_dir = Path.joinpath(BASE_DIR, 'media', 'thumbnail') local_image_dir.mkdir(parents=True, exist_ok=True) local_image_path = local_image_dir / imageName with open(local_image_path, 'wb+') as destination: destination.write(image)
(2)修正S3上传逻辑
只有当所有分片上传完成(end为1)时,才上传到S3,同时使用正确的客户端和路径:
# 补充bucket变量(需要从配置中获取) bucket = settings.AWS_STORAGE_BUCKET_NAME # 在end为1时执行S3上传 if int(end): # 使用已初始化的s3客户端,传入正确的本地文件路径 s3.upload_file(str(local_video_path), bucket, fileName_STR)
(3)其他细节修正
- 变量名统一:避免
fileName和fileName_STR混用,减少混淆 - Post模型创建时机:不要在每个分片请求都创建模型,应该在第一个分片时创建,后续分片更新模型状态
- 临时文件清理:上传完成到S3后,可以删除本地临时文件,节省存储空间
内容的提问来源于stack exchange,提问作者MrLonely
相关产品推荐
相关产品推荐

