obs_io.py
目录
1. 代码概述
这段代码的核心功能只有两件事:
- 从 OBS(对象存储)下载图片到本地
- 把本地图片上传到 OBS
同时:
- 支持 URL 中包含中文路径
- 使用 配置文件统一管理 AK / SK / bucket / server
- 所有操作都有 日志记录
2. 模块导入
from config import settings
- 项目配置文件
- 包含 AK / SK / bucket 名 / server 地址 / 本地目录等
from obs import ObsClient, PutObjectHeader
- 华为云 OBS SDK
ObsClient:访问 OBS 的客户端PutObjectHeader:上传时可设置对象头(这里其实没用上)
from config.logger_config import process_logger
- 项目里的日志对象
- 用于统一记录下载 / 上传 / 异常日志
from urllib.parse import unquote
- URL 解码工具
- 用来解决 中文路径 %E9%A9%AC%E6%B3%89%E8%90%A5 这种乱码问题
3. OBS 客户端初始化
3.1 下载客户端
download_obsClient = ObsClient(
access_key_id = settings.DOWNLOAD_AK,
secret_access_key = settings.DOWNLOAD_SK,
server = settings.DOWNLOAD_SERVER
)
作用:专门用于 从 OBS 下载,使用独立的 AK / SK / server
3.2 上传客户端
upload_obsClient = ObsClient(
access_key_id = settings.UPLOAD_AK,
secret_access_key = settings.UPLOAD_SK,
server = settings.UPLOAD_SERVER
)
作用:专门用于 上传到 OBS
3.3 PutObjectHeader(当前没用)
headers = PutObjectHeader()
headers.contentType = 'text/plain'
- 原本用于设置上传对象的
Content-Type - 但在
putFile()时 没有传 headers
4. download_from_obs 函数解析
4.1 函数定义
def download_from_obs(url, savedir=settings.DOWNLOAD_LOCAL_DIR):
参数:
url:带签名的 OBS 访问 URLsavedir:图片保存到本地的目录(默认配置里的目录)
4.2 URL 示例说明
"""
https://ip:port/bucket/xxx/.../%E9%A9%AC%E6%B3%89%E8%90%A5.jpg?AWSAccessKeyId=...
"""
注意点:
- 路径中包含 URL 编码的中文
- 后面带临时访问签名参数
4.3 URL 解码(重点)
url = unquote(url, encoding='utf-8')
作用:
- 把
%E9%A9%AC%E6%B3%89%E8%90%A5→马泉营 - 防止后续路径解析、文件名乱码
这是整段代码里 非常关键的一步
4.4 解析 OBS 内部对象路径
obs_image_path = url[
url.find("/", url.find(settings.DOWNLOAD_BUCKET_NAME)) + 1
: url.find(".jpg") + 4
]
假设 URL 是:
https://server/jt-zw/clzf/xxx/图片.jpg?参数
步骤:
- 找到 bucket 名出现的位置
- 从 bucket 后面的
/开始截取 - 一直截取到
.jpg结尾
最终得到:
clzf/OBCompany4/Picture/normal/.../马泉营.jpg
👉 这正是 OBS getObject() 需要的 objectKey
- 文件一定是
.jpg - URL 里一定只出现一次
.jpg
4.5 解析图片文件名
image_name = obs_image_path[obs_image_path.rfind("/")+1:]
得到:
马泉营.jpg
4.6 生成本地保存路径
images_save_path = os.path.join(os.path.abspath(savedir), image_name)
结果示例:
/data/images/马泉营.jpg
4.7 从 OBS 下载
resp = download_obsClient.getObject(
settings.DOWNLOAD_BUCKET_NAME,
obs_image_path,
downloadPath=images_save_path
)
含义:
- bucket:DOWNLOAD_BUCKET_NAME
- objectKey:obs_image_path
- downloadPath:保存到本地的完整路径
4.8 判断下载是否成功
if resp.status < 300:
- HTTP 状态码 < 300 → 成功
成功时:
return resp.status, images_save_path
失败时:
return resp.status, None
异常时:
return None, None
5. upload_to_obs 函数解析
5.1 函数定义
def upload_to_obs(img_fpath, obsdir=settings.UPLOAD_OBS_DIR):
参数:
img_fpath:本地图片完整路径obsdir:OBS 上的目标目录
5.2 获取文件名
img_fname = os.path.basename(img_fpath)
例如:
/data/images/马泉营.jpg → 马泉营.jpg
5.3 拼接 OBS 目标路径
obs_target_location = obsdir + "/" + img_fname
最终 objectKey:
processed/马泉营.jpg
5.4 上传文件
resp = upload_obsClient.putFile(
settings.UPLOAD_BUCKET_NAME,
obs_target_location,
img_fpath
)
含义:
- bucket:UPLOAD_BUCKET_NAME
- objectKey:obs_target_location
- 本地文件路径:img_fpath
5.5 上传结果处理
成功:
return resp.status, resp.body.objectUrl
失败:
return resp.status, None
异常:
return None, None
6. 最后一段注释代码的意义
decoded_str = unquote(mixed_str, encoding='utf-8')
这是一个 中文 URL 解码验证示例:
输入:
%E9%A9%AC%E6%B3%89%E8%90%A5
输出:
马泉营
👉 用来证明:
unquote() 可以正确处理 中英文混合字符串

浙公网安备 33010602011771号