目录
Opencv numpy arry图片非文件流直接上传
腾讯云COS服务器的文件上传和生命周期的设置
1.申请服务器
2.创建桶
3.官方文档以及安装SDK
4.开始使用(官方示例代码)
5.必要参数的获取
6.文件上传
7.上传接口参数解释
8.设置生命周期
我的全部测试实例代码:
使用opencv 做图像算法相关方面,经常会读取很多图片,然后对图像进行相关操作,也就是对矩阵运算,最后把处理后的图片保存或者上传服务器。普通操作就是把处理后的图片直接保存文件,而有可能面临这么一种情况,
你的领导觉得:处理后的图片---->保存文件流---->然后再读取文件----->再上传服务器,是很耗性能的以及耗时的。所以提出一个需求,处理的图片不保存文件流,直接上传服务器,这样就节约时间以及性能。因为图片处理后一般都是numpy array数组,直接通过特定技术,在内存中保存图片格式,然后上传服务器。
需要用到的库: PIL(需要安装 pip isntall PIL),io,numpy(需安装,我这里是演示读取的图片转换成numpy arr 格式)
演示:我这里会读取两张图片,转换成numpy格式来模拟opencv处理后的格式,存入一个列表。
img1 = Image.open("1.jpg")#第一张图
img1_array = np.array(img1)#转换为numpy array格式
可以看到打印后的图片,就是array格式:
接下来就是把numpy array不保存文件流,能够上传服务器。
import io
from PIL import Image
img = Image.fromarray(img1_array) # 转换为图像格式
# 创建buf,在内存中保存图片
buf = io.BytesIO()
img.save(buf, format="png")#内存中保存图片格式
to_upload_img = buf.getvalue() # 获取内存里面内容
上面代码虽然只有几行,但是能够实现这个复杂的需求。接下来就是对这几行代码进行分析。
Image.formarray()是PIL中的一个图像格式处理方法,把numpy数组,转换为图像格式储存。
io.BytesIO()是在内存中读写,之所以这样,省去了,把一个opencv处理后的图像矩阵数组,保存文件,再读取为二进制文件上传,节约了时间和性能。在内存中保存的时候,一定要指定图片格式。最后在获取内存里面的内容,就是我们需要的,就省去了保存文件,读取文件的过程。下面还有结合腾讯云上传图片的实例过程,有需要的看官,可以继续观看~
至于为什么用cos服务器?问就是两袖清风~留下贫穷的泪水~第一次使用,有6个月的免费使用期~
首先你得去申请自己的cos服务器(初次使用有6个月的免费体验期哦),申请传送门:https://cloud.tencent.com/product/cos
创建自己的储存桶,用来储存文件或者图片,我这里创建了一个图片储存的桶,权限是公有读私有写,官方说公有任何匿名用户都访问,官方推荐私有读,私有写。不过自己拿来测试的,任何都能访问,不能写挺好的,私有读的话,还要各种验证,对于我们来了解使用的,就暂时不必弄那么复杂。
有了桶之后,便可以做很多事情了,先附上腾讯云COS服务器官方文档(python):https://cloud.tencent.com/document/product/436/12269 (也有其他语言版本的,可以按照自己的所需,看对应语言的SDK文档)
安装SDK(不同语言安装的方式官方给的有对应的多种方法,我是用的python)
使用 pip 安装(推荐) (python安装sdk 的方式,其他语言请去对应的sdk文档按照方法安装)
pip install -U cos-python-sdk-v5
# -*- coding=utf-8
# appid 已在配置中移除,请在参数 Bucket 中带上 appid。Bucket 由 BucketName-APPID 组成
# 1. 设置用户配置, 包括 secretId,secretKey 以及 Region
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
import sys
import logging
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
secret_id = 'COS_SECRETID' # 替换为用户的 secretId
secret_key = 'COS_SECRETKEY' # 替换为用户的 secretKey
region = 'COS_REGION' # 替换为用户的 Region
token = None # 使用临时密钥需要传入 Token,默认为空,可不填
scheme = 'https' # 指定使用 http/https 协议来访问 COS,默认为 https,可不填
config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token, Scheme=scheme)
# 2. 获取客户端对象
client = CosS3Client(config)
# 参照下文的描述。或者参照 Demo 程序,详见 https://github.com/tencentyun/cos-python-sdk-v5/blob/master/qcloud_cos/demo.py
可以看到上面的代码引用了qcloud_cos包,就是安装sdk中的,logging是日志记录包,可以不用。剩下就是代码中一些关键的地方,secret_id,secret_key,region这三个必有的参数,表示你代码中访问桶所使用的账号ID,账号的key,以及服务器桶所属区域,至于这上面三个参数,需要登录腾讯云后:---->右上角的小人------>访问管理
进入访问管理后,选择左边的访问密钥,就能看到对应的ID和Key,当然腾讯云推荐创建子账号,用子账号访问。当然这个可以根据个人选择而定。
至于服务器桶所属区域怎么看,当你创建桶后,不论是代码还是腾讯云官方网页上手动创建,最后在储存桶列表能够看到属于区域。
然后看看腾讯云cos服务器文件上传的示例。
#### 文件流简单上传(不支持超过5G的文件,推荐使用下方高级上传接口)
# 强烈建议您以二进制模式(binary mode)打开文件,否则可能会导致错误
with open('picture.jpg', 'rb') as fp:
response = client.put_object(
Bucket='examplebucket-1250000000',
Body=fp,
Key='picture.jpg',
StorageClass='STANDARD',
EnableMD5=False
)
print(response['ETag'])
#### 字节流简单上传
response = client.put_object(
Bucket='examplebucket-1250000000',
Body=b'bytes',
Key='picture.jpg',
EnableMD5=False
)
print(response['ETag'])
#### chunk 简单上传
import requests
stream = requests.get('https://cloud.tencent.com/document/product/436/7778')
# 网络流将以 Transfer-Encoding:chunked 的方式传输到 COS
response = client.put_object(
Bucket='examplebucket-1250000000',
Body=stream,
Key='picture.jpg'
)
print(response['ETag'])
#### 高级上传接口(推荐)
# 根据文件大小自动选择简单上传或分块上传,分块上传具备断点续传功能。
response = client.upload_file(
Bucket='examplebucket-1250000000',
LocalFilePath='local.txt',
Key='picture.jpg',
PartSize=1,
MAXThread=10,
EnableMD5=False
)
print(response['ETag'])
上面代码是腾讯云官方给的python版上传文件的示例,官当推荐高级上传接口,有断点续传功能。
我对上面部分通用代进行解释一下,因为官方写的文档有些不完整,需要自己用代码后收手动测试才知道是干嘛的。
Bucket:需要储存桶的名字 Body:需要储存的二进制文件
Key:需要特别说明一下,Key指的是上传文件后,文件在服务器的名字或者路径名字(比如,如果你的key命名为1.jpg,就会直接在桶储存你上传的文件在桶的名字为1.jpg,如果有路径,比如我key是image/2020-7-25/1.1pg,就会在桶里面创建image文件夹,里面有个2020-7-25的文件夹,然后这个日期文件夹里面有一个1.jpg)
locapath:是高级上传接口,需要上传文件的本地路径。
我当初还不知道为什么要设置生命周期,因为腾讯云用的cos服务器是储存容量无限制的。在公司工作中带我的大佬,让我看看腾讯云cos服务器收费规则后顿时明了。看到下面的图片有:存储容量费用 = 存储容量单价 * 月存储容量,懂了吧?就是储存的越多,扣的钱越多,难怪我说,明明是免费的,上次显示我的欠费了,让我交了1毛,幸亏当初测试自己的cos服务器,上传的文件不多。腾讯云cos服务器名义上是第一次使用,6个月免费试用期,实际上如果储存了东西,月底还是要收费的,对于公司项目来说,肯定随着时间的积累,文件越来越多,造成的费用也会越来越高,所以需要定期清理不重要的数据或者文件,保留重要的数据,已减轻财务的压力。毕竟钱越来越难挣了,一般的公司也不例外。
所以为了节约money,需要定期清理文件,也就是设置生命周期,到设置的时间自动清理掉。
方法原型
put_bucket_lifecycle(Bucket, LifecycleConfiguration={}, **kwargs)
请求实例:
from qcloud_cos import get_date
response = client.put_bucket_lifecycle(
Bucket='examplebucket-1250000000',
LifecycleConfiguration={
'Rule': [
{
'ID': 'string',
'Filter': {
'Prefix': 'string',
'Tag': [
{
'Key': 'string',
'Value': 'string'
}
]
},
'Status': 'Enabled'|'Disabled',
'Expiration': {
'Days': 100,
'Date': get_date(2018, 4, 20)
},
'Transition': [
{
'Days': 100,
'Date': get_date(2018, 4, 20),
'StorageClass': 'Standard_IA'|'Archive'
},
],
'NoncurrentVersionExpiration': {
'NoncurrentDays': 100
},
'NoncurrentVersionTransition': [
{
'NoncurrentDays': 100,
'StorageClass': 'Standard_IA'
},
],
'AbortIncompleteMultipartUpload': {
'DaysAfterInitiation': 100
}
}
]
}
)
参数说明
参数名称 | 参数描述 | 类型 | 必填 |
---|---|---|---|
Bucket | 存储桶名称,由 BucketName-APPID 构成 | String | 是 |
Rule | 设置对应的规则,包括 ID,Filter,Status,Expiration,Transition,NoncurrentVersionExpiration,NoncurrentVersionTransition,AbortIncompleteMultipartUpload | List | 是 |
ID | 设置规则的 ID | String | 否 |
Filter | 用于描述规则影响的 Object 集合,如需设置 Bucket 中的所有 objects,请设置 Prefix 为空'' | Dict | 是 |
Status | 设置 Rule 是否启用,可选值为 Enabled 或者 Disabled | Dict | 是 |
Expiration | 设置 Object 过期规则,可以指定天数 Days 或者指定日期 Date,Date 的格式必须是 GMT ISO 8601,建议使用 get_date 方法来指定具体的日期 | Dict | 否 |
Transition | 设置 Object 转换存储类型规则,可以指定天数 Days 或者指定日期 Date,Date 的格式必须是 GMT ISO 8601,建议使用 get_date 方法来指定具体的日期。StorageClass 可选 Standard_IA,Archive,可以同时设置多条此类规则 | List | 否 |
NoncurrentVersionExpiration | 设置非当前版本 Object 过期规则,可以指定天数 NoncurrentDays | Dict | 否 |
NoncurrentVersionTransition | 设置非当前版本 Object 转换存储类型规则,可以指定天数 NoncurrentDays,StorageClass 可选 Standard_IA,可以同时设置多条此类规则 | List | 否 |
AbortIncompleteMultipartUpload | 指明分块上传开始后多少天内必须完成上传 | Dict | 否 |
生命周期应该是文档写的算是最完整的,上传的文件的代码就没有文档,完全代码示例。如果还需要其他功能,可以腾讯云官方查看文档,文档传送门:https://cloud.tencent.com/document/product
接下来我附上我个人的代码:是基于带我的大佬给我提出的需求:opencv项目分析会产生很多图片,不过图片不是普通那种图片格式,而是numpy array数组,让我不经过保存文件形式上传到cos服务器。所以就有了这篇文章。我用到的前面基本都讲了,现在我就把我写的测试代码放出来。可以本地测试多个图片,转换成numpy arr数组形式,然后传给文件上传函数,在内存中处理后上传到服务器。先给各位看官看下效果。
上传成功后,返回文文件上传的url地址,同时也把生命周期设置打印出来。
服务器:可以看到image文件夹下有日期命名的分类文件夹,对应的日期有当天上传的文件。
点击文件详情你还能看到文件详细信息,例如地址,文件大小,时间等
# -*- coding: utf-8 -*-
import io
import numpy as np
import uuid
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
import time, os, glob
from PIL import Image
class LegacyFunctions():
#不符合新的需求,所以该方法没用了,可以拿来参考
@staticmethod
def upload_file(self, bucket_name, file_path):
"""
当前上传文件方法是基于腾讯云高级接口写的文件流的方式上传图片,
能够实现传入的文件夹地址内的所有文件上传到指定cos服务器
因为新框架是传入numpy数组,不会保存文件流,需要用字节流的方式上传
:param bucket_name: 桶的名字
:param file_path: 本地文件名字
"""
file_list = os.listdir(file_path) # 列举文件夹内文件
# print(file_list)
#### 高级上传接口(腾讯云cos服务器)
# 根据文件大小自动选择简单上传或分块上传,分块上传具备断点续传功能。
for file_name in file_list:
file_name_path = os.path.join(file_path, file_name) # 本地每个文件地址
response = self.client.upload_file(
Bucket=bucket_name,
LocalFilePath=file_name_path, # 上传的时候本地文件路径
Key="image/" + str(self.date) + '/' + file_name, # 上传到服务器的路径和文件名字
PartSize=1,
MAXThread=10,
EnableMD5=False
)
print("文件ETag编号:" + response['ETag'])
print("***********%d张图片上传cos服务器成功!*********" % len(file_list))
@staticmethod
def delete_image(self, file_path): # 删除图片
"""
当前方法是基于原项目生成图片到static目录下,上传完毕后删除本地图片
因为新的框架不以文件流保存,该方法就不用了
:param self:
:param file_path:
"""
file_path = file_path + '/*.jpg'
lis = glob.glob(file_path)
for image in lis:
os.remove(image)
class FileUploader():
def __init__(self, bucket_name, secret_id, secret_key, cos_region, token=None, schem=None):
"""
通过server_config.py中的配置加载相关参数
:param bucket_name: cos服务器桶的名字
:param secret_id: 用户的 secretId
:param secret_key:用户的 secretKey
:param cos_region:服务器地区
:param token:使用临时密钥需要传入 Token,默认为空,可不填
:param schem:指定使用 http/https 协议来访问 COS,默认为 https,可不填
"""
self.bucket_name = bucket_name
self.secret_id = secret_key
self.secret_key = secret_key
self.region = cos_region
self.token = token
self.scheme = schem
self.date = time.strftime("%Y-%m-%d")
self.config = CosConfig(Region=cos_region, SecretId=secret_id, SecretKey=secret_key,
Token=token, Scheme=schem)
def uuid_generate(self):
"""生成唯一的id"""
uuid_code = uuid.uuid1()
return uuid_code
def set_lifecycle(self, ttl_days):
"""
设置桶的生命周期,官方返回值为None
:param ttl_days: 生命周期天数
:uuid :每张图片唯一标识符
"""
client = CosS3Client(self.config)
response = client.put_bucket_lifecycle(
Bucket=self.bucket_name,
LifecycleConfiguration={
'Rule': [
{
'ID': self.secret_id, # 设置规则的 ID,实际上是规则的名字
'Filter': {
'Prefix': '', # 重要:用于描述规则影响的 Objects 集合,如需设置 Bucket 中的所有 objects,请设置 Prefix 为空''
},
'Status': 'Enabled', # 设置 Rule 是否启用,可选值为 Enabled 或者 Disabled
'Expiration': { # 生命周期(设置 Object 过期规则,可以指定天数 Days 或者指定日期 Date)
'Days': ttl_days
},
'AbortIncompleteMultipartUpload': { # 指明分块上传开始后多少天内必须完成上传
'DaysAfterInitiation': 7
}
}
]
}
)
def getlifecycle(self):
"""
查询生命周期
:return: 生命周期的配置,类型:字典
"""
client = CosS3Client(self.config)
response = client.get_bucket_lifecycle(
Bucket=self.bucket_name,
)
return response
def upload(self, to_upload_files, ttl_days):
"""
:param to_upload_files: 传入的numpy矩阵图片列表
:param ttl_days: 生命周期天数
:return: 上传成功后的url列表
"""
# 获取客户端对象
client = CosS3Client(self.config)
to_return_url_list = [] # 存url的列表
for img_nparray in to_upload_files:
img = Image.fromarray(img_nparray) # 转换为图像格式
# 创建buf,在内存中保存图片
buf = io.BytesIO()
img.save(buf, format="png")
to_upload_img = buf.getvalue() # 获取BytesIO里面内容
uuid_code = str(self.uuid_generate())
cos_server_file_path = "image/" + str(self.date) + '/' + uuid_code + '.png' # 上传到服务器的路径和保存的文件名字
# 字节流简单上传
response = client.put_object(
Bucket=self.bucket_name,
Body=to_upload_img, # 上传文件的字节流或者文件流
Key=cos_server_file_path
)
"""由于返回的信息没有url,但是可以根据规律拼接上传文件后的url"""
url = 'https://' + self.bucket_name + '.cos.' + self.region + '.myqcloud.com/' + cos_server_file_path
to_return_url_list.append(url)
# 调用方法设置生命周期
self.set_lifecycle(ttl_days)
return to_return_url_list
if __name__ == '__main__':
# 以下信息是属于lyt个人测试cos服务器信息,需要换成自己的cos信息
bucket_name = BUCKET_NAME
secret_id = SECRET_ID
secret_key = SECRT_KEY
cos_region = COS_REGION
cos_server = FileUploader(bucket_name, secret_id, secret_key, cos_region)
""""读入两张测试图片,用来测试"""
nparray_list = []
img1 = Image.open("1.jpg")
img1_array = np.array(img1)
nparray_list.append(img1_array)
img2 = Image.open("2.jpg")
img2_array = np.array(img2)
nparray_list.append(img2_array)
print(nparray_list)
"""上传文件"""
url_list = cos_server.upload(nparray_list, 1)
print(url_list)
"""查询生命周期相关参数"""
life_cycle = cos_server.getlifecycle()
print(life_cycle)
喜欢大佬们,可以给我点点赞或者关注~