背景
最近在研究一个剪贴板粘贴工具,实现粘贴图片,返回可访问的地址,这个在我的哔哩哔哩上有出一期视频🤭。但是,我发现部分博客平台不能正常的转载我的图片链接,于是研究了一下腾讯云的COS(阿里的叫OSS,最开始我还不知道腾讯云的叫COS🥹),想着其它平台应该可以转载这个在线的地址吧🤭。我的最终的效果如下:
本期文章,我不会教大家如何的开通腾讯云的COS,如何去上传文件,我只会展示我觉得我代码设计的亮点,以及可以去分享的地方。不会如何对接的,参考COS python SDK文档
我的项目设计的亮点有:
- 开发的密钥脱离代码,单独放在服务器上
- 工具类的定义和代码分层
- 可以提供本地使用(cmd命令行)
下边我将逐一分析。
亮点
开发的密钥脱离代码
按照我的常识,我们的代码中的配置项是固定的字符串的话,可以分为5种情况讨论,来看看程序员对代码的负责程度和写代码的规范性。
level one
Credit credit = new Credit("admin", "admin");
直接在代码里干,读过阿里巴巴《Java开发规范》的都知道,这出现了魔法值,不符合规范。
level two
private static final String USERNAME = "admin";
private static final String PASSWORD = "admin";
Credit credit = new Credit(USERNAME, PASSWORD);
用静态的常量写,摆脱了魔法值,方便修改。但是还是不优雅,业务类里边加上了配置的代码。而且,配置很散,配置项的堆积直接造成屎山
的产生。
level three
public class AuthConfig {
private String username = "admin";
private String password = "admin";
}
public class Service {
private AuthConfig config;
// 省略业务逻辑
Credit credit = new Credit(config.username, config.password);
}
现在舒服多了,配置项那么多,我都通过类来隔离了,要哪个导入哪个。但是,细心的或者说比较喜欢精益求精的你,这样安全吗?特别是具有特别高权限的账户密码,得到了是不是可以为所欲为了?
Level four
这一级别基本上懂点
spring cloud
的配置组件了,别提spring cloud config
了,我用的是nacos
,全称不要忘记了,namespace and config system
。这一级别,很好的防治了为所欲为的产生,因为我有配置中心,稍微一管控,不是任何人都可以看到的。
nacos
怎么用,自己百度去吧。看看yml
文件:
auth:
username: admin
password: admin
java
代码是这样的:
@ConfigurationProperties(prefix = "auth")
@Component
@Data
public class AuthConfig {
private String username;
private String password;
}
怎么样,是不是简单。记得用上lombok
。除此之外,我还可以实现在nacos
上的更改,我服务可以动态的获得新配置,不用重启服务!
level five
最后一级了,终极大招!安全度98%
,除非开放了服务器的root
访问权限。
这样,先看看代码,我用python
写的,各种编程语言异曲同工。
class COSUtil():
def __init__(self) -> NoReturn:
config_file = os.path.expanduser('~') + '/.tencentcloud/tencent.json'
if not os.path.isfile(config_file):
raise FileNotFoundError
with open(config_file, 'r') as file:
config_data = json.load(file)
if not config_data:
raise ValueError('config file is empty')
secret_id = config_data['SecretId']
secret_key = config_data['SecretKey']
self.default_bucket = config_data['defaultBucket']
self.region = 'ap-shanghai'
config = CosConfig(Region=self.region, SecretId=secret_id, SecretKey=secret_key)
client = CosS3Client(config)
self.client = client
巧妙点就在于我的配置文件完全在服务器,与代码无关。有人说:我的是docker容器部署的怎么办。怎么办?重学docker,docker的文件挂载忘啦。
OK,读取文件的内容,再转化成一个对象,根据key获得对应的配置。巧啊,妙啊,优雅。别问我怎么学到的,我看腾讯云的CDB sdk源码获得的。
是不是觉得很神奇,觉得神奇的话,记得点赞、在看、转发、关注哈
工具类的定义和代码分层
我的类定义和__init__
初始化已经在上边罗列了。那我要上传文件怎么玩?直接一个方法安排上!
def upload_file_binary(self, filepath:str, bucket: Optional[str]= None, filename: Optional[str]= None) -> str:
"""二进制上传
Args:
filepath (str): _description_
bucket (_type_, optional): _description_. Defaults to Optional[String].
filename (_type_, optional): 文件名,可以指定在存储桶中的位置. Defaults to Optional[String].
Raises:
FileNotFoundError: _description_
Returns:
str: 文件的预览地址
"""
if not os.path.isfile(filepath):
raise FileNotFoundError
key = filename or os.path.basename(filepath)
with open(filepath, 'rb') as fp:
self.client.put_object(
Bucket= bucket or self.default_bucket,
Body=fp,
Key=key,
StorageClass='STANDARD',
EnableMD5=False
)
return self.get_preview_url(key)
说实话,自己都觉得巨优雅。方法上参数的类型约束、方法文档,我觉得都很无懈可击。直接调用我的方法就可以看到我的方法是干什么的,需要什么参数。
cmd中使用
工具类的意义就是简化方法的调用,代码的耦合度。我很喜欢我的mac,可以给我提供linux的开发环境,让我各种倒腾。先看效果:
是不是觉得很好用了。我本地只需要这样就可以上传图片获得文件的在线地址(预览地址)。
cos 文件的相对路径/绝对路径
怎么实现的呢?来看看:
if __name__ == '__main__':
cosUtil = COSUtil()
# print(cosUtil.list_buckets())
print('upload local file to COS bucket')
filepath = sys.argv[1]
if not filepath or not os.path.isfile(filepath):
raise FileExistsError(f'{filepath}')
preview_path = cosUtil.upload_file_binary(filepath)
print(f'successfully uploaded, preview_url: {preview_path}')
其实浓缩起来,一行代码就可以解决。
我另外需要配置一个alias
,记得在.bash_profile
中配置。不会这个文件的,建议百度学习一下。
alias cos="python3 xxxx/cos.py $*"
$*表示把控制台参数全部传递给python的
__main__
。
至此,我的COS被我整的很nice了。