Cloud Function使用tmp目录暂存图片上传时报路径不存在错误
问题根因
报错来自上传逻辑的两个低级错误:
- 硬编码字符串切片拆分路径:你写的
filename = fullpath[7:]、path = fullpath[0:6]是完全写死的字符偏移量,本地暂存图片路径为/tmp/[文件名].jpg时,这种切法会把文件名的首字符切到路径里,最终拼出不存在的路径,即你遇到的报错:
[Errno 2] No such file or directory: '/tmp/h/cabujfoh.jpg'
- 上传代码缩进错误:遍历图片的for循环只执行了打印操作,真正的Blob初始化、文件上传、URL收集逻辑全在循环外部,只会执行一次,无法批量处理所有图片。
修复方案
- 删掉所有硬编码切片拆分本地路径的逻辑,本地图片的完整路径已经由
optimizeImage函数返回,直接使用即可 - 修正代码缩进,将上传逻辑移入图片遍历循环内部,确保每张图都被处理
- 所有路径拼接统一使用
os.path.join,不要手动拼接斜杠,避免路径格式错误 - (可选)升级Pillow库兼容写法:Pillow 9.1.0及以上版本已经废弃
Image.ANTIALIAS,替换为Image.Resampling.LANCZOS即可
修复后代码
修正后的辅助函数
import os import urllib.request import string import random from PIL import Image # 图片下载函数 def dl_jpg(url, file_path, file_name): full_path = os.path.join(file_path, f"{file_name}.jpg") urllib.request.urlretrieve(url, full_path) return full_path # 图片优化函数 def optimizeImage(name) -> str: img_local_path = os.path.join('/tmp/', f"{name}.jpg") foo = Image.open(img_local_path) # 旧版本Pillow可把下面的Image.Resampling.LANCZOS换回Image.ANTIALIAS foo = foo.resize((525,394), Image.Resampling.LANCZOS) foo.save(img_local_path, optimize=True, quality=50) print(f'Optimized Image: {name}') return img_local_path # 随机文件名生成函数 def random_name() -> str: letters = string.ascii_lowercase return ''.join(random.choice(letters) for i in range(10))
修正后的上传逻辑
ref = db.collection('listings').document() photos = [] # 提前初始化bucket,不要放到循环里重复初始化 bucket = store.get_bucket('testxxxxxx2365963.appspot.com') # 遍历所有本地优化完成的图片 for image_local_path in listing.photos: # 从完整路径直接提取文件名,不需要硬编码切片 filename = os.path.basename(image_local_path) # 构建Cloud Storage存储路径 blob = bucket.blob(f'ListingImages/{ref.id}/{filename}') # 直接用完整本地路径上传 blob.upload_from_filename(image_local_path) blob.make_public() photos.append(blob.public_url) # 后续将photos数组和其他业务数据一起写入ref对应的Firestore文档即可
额外建议
如果是批量跑爬虫任务,建议在每张图片上传完成后调用os.remove(image_local_path)删除/tmp下的临时文件,避免临时目录占满磁盘导致后续任务失败。
内容的提问来源于stack exchange,提问作者Rene Alas
相关产品推荐
相关产品推荐

