auto-sync: tencent-cos-upload 2026-04-10_19:54
This commit is contained in:
commit
0140cf9ae7
94
SKILL.md
Normal file
94
SKILL.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
name: tencent-cos-upload
|
||||||
|
description: 上传文件到腾讯云COS并生成可直接访问的URL。当需要将本地文件(图片、视频、音频、文档等)上传到腾讯云对象存储,并获取公开可访问链接时使用。触发场景:上传文件到COS、生成文件外链、存储媒体资源、备份文件到云端。
|
||||||
|
---
|
||||||
|
|
||||||
|
# 腾讯云COS文件上传
|
||||||
|
|
||||||
|
将本地文件上传到腾讯云COS,返回可直接访问的URL。
|
||||||
|
|
||||||
|
## 前置依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip3 install cos-python-sdk-v5 --break-system-packages
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用方式
|
||||||
|
|
||||||
|
### 方式一:调用脚本(推荐)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 scripts/cos_upload.py <local_file> <cos_key> [--content-type <mime_type>]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `local_file`:本地文件路径
|
||||||
|
- `cos_key`:COS上的存储路径(如 `vala_llm/data/image.png`)
|
||||||
|
- `--content-type`:可选,MIME类型(如 `image/png`),不指定则自动检测
|
||||||
|
|
||||||
|
输出一行URL:`https://<domain>/<cos_key>`
|
||||||
|
|
||||||
|
示例:
|
||||||
|
```bash
|
||||||
|
python3 scripts/cos_upload.py /tmp/photo.png vala_llm/user_feedback/image/2026-04-10/abc123.png
|
||||||
|
# 输出: https://static.valavala.com/vala_llm/user_feedback/image/2026-04-10/abc123.png
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式二:Python代码引用
|
||||||
|
|
||||||
|
```python
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, '/root/.openclaw/skills/tencent-cos-upload/scripts')
|
||||||
|
from cos_upload import CosUploader
|
||||||
|
|
||||||
|
uploader = CosUploader()
|
||||||
|
url = uploader.upload('/tmp/photo.png', 'vala_llm/images/photo.png')
|
||||||
|
print(url) # https://static.valavala.com/vala_llm/images/photo.png
|
||||||
|
```
|
||||||
|
|
||||||
|
批量上传:
|
||||||
|
```python
|
||||||
|
results = uploader.upload_batch([
|
||||||
|
('/tmp/a.png', 'path/a.png'),
|
||||||
|
('/tmp/b.mp4', 'path/b.mp4'),
|
||||||
|
])
|
||||||
|
# results = [('path/a.png', 'https://...'), ('path/b.png', 'https://...')]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置
|
||||||
|
|
||||||
|
凭证从 `secrets.md` 的腾讯云COS部分读取,脚本中通过硬编码加载(非环境变量)。
|
||||||
|
|
||||||
|
如需修改配置(换桶、换域名),编辑 `scripts/cos_upload.py` 顶部的常量。
|
||||||
|
|
||||||
|
## COS路径规范
|
||||||
|
|
||||||
|
建议按 `{业务}/{类型}/{日期}/` 组织:
|
||||||
|
```
|
||||||
|
vala_llm/
|
||||||
|
├── user_feedback/
|
||||||
|
│ ├── image/2026-04-10/
|
||||||
|
│ ├── video/2026-04-10/
|
||||||
|
│ ├── audio/2026-04-10/
|
||||||
|
│ └── file/2026-04-10/
|
||||||
|
└── asr_audio_backup/
|
||||||
|
├── online/20260410/
|
||||||
|
└── test/20260410/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 文件名规范
|
||||||
|
|
||||||
|
- 避免中文,使用纯ASCII字符(字母、数字、短横线、下划线)
|
||||||
|
- 推荐格式:`{唯一ID}{扩展名}`,如 `abc123def456.png`
|
||||||
|
|
||||||
|
## 常见MIME类型
|
||||||
|
|
||||||
|
| 扩展名 | Content-Type |
|
||||||
|
|--------|-------------|
|
||||||
|
| .png | image/png |
|
||||||
|
| .jpg/.jpeg | image/jpeg |
|
||||||
|
| .mp4 | video/mp4 |
|
||||||
|
| .mov | video/quicktime |
|
||||||
|
| .mp3 | audio/mpeg |
|
||||||
|
| .ogg | audio/ogg |
|
||||||
|
| .wav | audio/wav |
|
||||||
|
| .pdf | application/pdf |
|
||||||
123
scripts/cos_upload.py
Normal file
123
scripts/cos_upload.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
腾讯云COS文件上传工具
|
||||||
|
用法:
|
||||||
|
python3 cos_upload.py <local_file> <cos_key> [--content-type <mime>]
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import mimetypes
|
||||||
|
import argparse
|
||||||
|
from qcloud_cos import CosConfig, CosS3Client
|
||||||
|
|
||||||
|
# ============ 配置(修改这里切换桶/域名)============
|
||||||
|
COS_SECRET_ID = "AKIDpbWMzOYaP2UltHWccS4TJJDxX1Pfkvzt"
|
||||||
|
COS_SECRET_KEY = "ythOwofOxvtklL3XpxsaChEbntqhOrFi"
|
||||||
|
COS_REGION = "ap-beijing"
|
||||||
|
COS_BUCKET = "static-1317843270"
|
||||||
|
COS_DOWNLOAD_DOMAIN = "static.valavala.com"
|
||||||
|
|
||||||
|
|
||||||
|
class CosUploader:
|
||||||
|
"""腾讯云COS上传器"""
|
||||||
|
|
||||||
|
def __init__(self, secret_id=None, secret_key=None, region=None, bucket=None, domain=None):
|
||||||
|
self.bucket = bucket or COS_BUCKET
|
||||||
|
self.domain = domain or COS_DOWNLOAD_DOMAIN
|
||||||
|
config = CosConfig(
|
||||||
|
Region=region or COS_REGION,
|
||||||
|
SecretId=secret_id or COS_SECRET_ID,
|
||||||
|
SecretKey=secret_key or COS_SECRET_KEY,
|
||||||
|
Scheme='https'
|
||||||
|
)
|
||||||
|
self.client = CosS3Client(config)
|
||||||
|
|
||||||
|
def upload(self, local_path: str, cos_key: str, content_type: str = None) -> str:
|
||||||
|
"""
|
||||||
|
上传文件到COS
|
||||||
|
Args:
|
||||||
|
local_path: 本地文件路径
|
||||||
|
cos_key: COS存储路径
|
||||||
|
content_type: MIME类型,不指定则自动检测
|
||||||
|
Returns:
|
||||||
|
可访问的URL
|
||||||
|
"""
|
||||||
|
if not os.path.exists(local_path):
|
||||||
|
raise FileNotFoundError(f"文件不存在: {local_path}")
|
||||||
|
|
||||||
|
if not content_type:
|
||||||
|
content_type = self._detect_content_type(local_path)
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
'Bucket': self.bucket,
|
||||||
|
'Key': cos_key,
|
||||||
|
'LocalFilePath': local_path,
|
||||||
|
}
|
||||||
|
if content_type:
|
||||||
|
kwargs['ContentType'] = content_type
|
||||||
|
|
||||||
|
self.client.upload_file(**kwargs)
|
||||||
|
return f"https://{self.domain}/{cos_key}"
|
||||||
|
|
||||||
|
def upload_bytes(self, data: bytes, cos_key: str, content_type: str = None) -> str:
|
||||||
|
"""上传字节数据到COS"""
|
||||||
|
kwargs = {
|
||||||
|
'Bucket': self.bucket,
|
||||||
|
'Key': cos_key,
|
||||||
|
'Body': data,
|
||||||
|
}
|
||||||
|
if content_type:
|
||||||
|
kwargs['ContentType'] = content_type
|
||||||
|
self.client.put_object(**kwargs)
|
||||||
|
return f"https://{self.domain}/{cos_key}"
|
||||||
|
|
||||||
|
def upload_batch(self, items: list) -> list:
|
||||||
|
"""
|
||||||
|
批量上传
|
||||||
|
Args:
|
||||||
|
items: [(local_path, cos_key), ...] 或 [(local_path, cos_key, content_type), ...]
|
||||||
|
Returns:
|
||||||
|
[(cos_key, url), ...]
|
||||||
|
"""
|
||||||
|
results = []
|
||||||
|
for item in items:
|
||||||
|
local_path = item[0]
|
||||||
|
cos_key = item[1]
|
||||||
|
content_type = item[2] if len(item) > 2 else None
|
||||||
|
try:
|
||||||
|
url = self.upload(local_path, cos_key, content_type)
|
||||||
|
results.append((cos_key, url))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] 上传失败 {cos_key}: {e}", file=sys.stderr)
|
||||||
|
results.append((cos_key, None))
|
||||||
|
return results
|
||||||
|
|
||||||
|
def delete(self, cos_key: str):
|
||||||
|
"""删除COS上的文件"""
|
||||||
|
self.client.delete_object(Bucket=self.bucket, Key=cos_key)
|
||||||
|
|
||||||
|
def list_objects(self, prefix: str, max_keys: int = 100) -> list:
|
||||||
|
"""列出COS上的文件"""
|
||||||
|
resp = self.client.list_objects(Bucket=self.bucket, Prefix=prefix, MaxKeys=max_keys)
|
||||||
|
return [item['Key'] for item in resp.get('Contents', []) if not item['Key'].endswith('/')]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _detect_content_type(filepath: str) -> str:
|
||||||
|
mime, _ = mimetypes.guess_type(filepath)
|
||||||
|
return mime or 'application/octet-stream'
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='上传文件到腾讯云COS')
|
||||||
|
parser.add_argument('local_file', help='本地文件路径')
|
||||||
|
parser.add_argument('cos_key', help='COS存储路径')
|
||||||
|
parser.add_argument('--content-type', help='MIME类型(自动检测)', default=None)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
uploader = CosUploader()
|
||||||
|
url = uploader.upload(args.local_file, args.cos_key, args.content_type)
|
||||||
|
print(url)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Loading…
Reference in New Issue
Block a user