阿里云OSS使用笔记


记得上次,大概3个月前,我使用阿里云PHP SDK试了很久实现不了文件上传到OSS功能。现在随便试了下Python SDK,复制代码两分钟便实现了文件上传至阿里云OSS,由此,便写下了这篇关于OSS的使用笔记。

在这之前,我是使用硅云服务器备份我的数据库,之前购买的价格便宜,一个月5元左右,不过现在没有优惠了,一年200元,我肯定不会选择这种方案。早都发现了阿里云OSS有备份文件数据的功能,但之前使用PHP SDK没成功。这次,基本可以使用OSS备份文件的方案了。另外,阿里云OSS可以提供类似于静态网页功能,可以使用该HTTP服务提供网页浏览、文件下载等功能。

(1)Python上传文件

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import oss2

# 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
auth = oss2.Auth('LTAIF0txxxxxxx', 'MIvATY6wZUpymoxxxxxxxxxx')
# Endpoint以杭州为例,其它Region请按实际情况填写。
bucket = oss2.Bucket(auth, 'http://oss-cn-shenzhen.aliyuncs.com', 'xxxx-shenzhen')

# 必须以二进制的方式打开文件,因为需要知道文件包含的字节数。
with open('697fe033d50b2b2c646964b012d4e4cf.jpg', 'rb') as fileobj:
    # Seek方法用于指定从第1000个字节位置开始读写。上传时会从您指定的第1000个字节位置开始上传,直到文件结束。
    # fileobj.seek(1000, os.SEEK_SET)
    # Tell方法用于返回当前位置。
    current = fileobj.tell()
    # put_object第一个参数为对象名,即文件名,或者绝对路径/backup/aaa.zip
    bucket.put_object('697fe033d50b2b2c646964b012d4e4cf.jpg', fileobj)
# bucket.put_object_from_file('<yourObjectName>', '<yourLocalFile>')

697fe033d50b2b2c646964b012d4e4cf.jpg即为上传之后的文件

(2)发布静态网站

1)设置Bucket权限为公共读

2)设置静态网站首页页面

3)添加自己的域名

到域名管理选项卡,点击添加自己的域名即可;注意域名需要CNAME到Bucket的外网访问域名。

4)浏览器访问静态网站

5)问题:为什么不使用OSS自带的域名?

如果直接使用OSS默认域名从互联网访问OSS上网页类型文件,Response Header中会自动加上Content-Disposition:'attachment=filename;'。即从浏览器访问网页类型文件时,会以附件形式进行下载。

(3)实现MySQL数据库自动备份到阿里云OSS

1)首先编写python脚本实现数据库备份和上传至阿里云OSS

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import oss2,requests,os,datetime,time,socket,sys
host = socket.gethostname()
timestr=datetime.datetime.now().strftime('%Y%m%d%H%M%S')
timestamp=time.time()
path = "/home/www/database/"
file = "database-xxx-"+timestr+".sql.gz"
os.system("/usr/bin/mysqldump -uroot -ppassword database |gzip > "+path+file)

auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
bucket = oss2.Bucket(auth, 'http://oss-cn-shenzhen.aliyuncs.com', 'xxxxx')
with open(path+file, 'rb') as fileobj:
    current = fileobj.tell()
    bucket.put_object(file, fileobj)
    print('上传成功')

2)配置定时任务,每天23:56执行备份。

56 23 * * * python3 /home/alioss.py

(4)PHP使用SDK上传文件到阿里云OSS

上次操作可能有误导致文件上传OSS失败,这次(2019-07-22)便能操作成功了,和Python一样,安装依赖包,复制文档demo。

namespace app\tools\controller;
use think\Controller;
use OSS\OssClient;
use OSS\Core\OssException;
class Aliyun extends Controller
{
    /**
     * 阿里云存储上传文件
     * 2019-07-22
     * @return \think\Response
     */
    public function upload(){
        $accessKeyId = "<yourAccessKeyId>";
        $accessKeySecret = "<yourAccessKeySecret>";
        $endpoint = "http://oss-cn-shenzhen.aliyuncs.com";
        $bucket= "linzening-shenzhen"; // 存储空间名称
        $object = "favicon.ico"; // 上传到OSS的保存文件名称及路径
        $filePath = "./favicon.ico"; // 本地文件路径
        try{
            $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);

            $ossClient->uploadFile($bucket, $object, $filePath);
        } catch(OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }

    /**
     * 阿里云存储列表
     * 2019-07-22
     * @return \think\Response
     */
    public function list(){
        $accessKeyId = "<yourAccessKeyId>";
        $accessKeySecret = "<yourAccessKeySecret>";
        $endpoint = "http://oss-cn-shenzhen.aliyuncs.com";
        $bucket= "linzening-shenzhen"; // 存储空间名称

        $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);

        while (true) {
            try {
                $listObjectInfo = $ossClient->listObjects($bucket);
            } catch (OssException $e) {
                printf(__FUNCTION__ . ": FAILED\n");
                printf($e->getMessage() . "\n");
                return;
            }
            // 得到nextMarker,从上一次listObjects读到的最后一个文件的下一个文件开始继续获取文件列表。
            $nextMarker = $listObjectInfo->getNextMarker();
            $listObject = $listObjectInfo->getObjectList();
            $listPrefix = $listObjectInfo->getPrefixList();

            if (!empty($listObject)) {
                print("objectList:\n");
                foreach ($listObject as $objectInfo) {
                    print($objectInfo->getKey() . "\n");
                }
            }
            if (!empty($listPrefix)) {
                print("prefixList: \n");
                foreach ($listPrefix as $prefixInfo) {
                    print($prefixInfo->getPrefix() . "\n");
                }
            }
            if ($nextMarker === '') {
                break;
            }
        }
    }
}

upload: OK

如果是要列举 images 目录下的文件:

$options = array(
    'delimiter' => '/',
    'prefix' => 'images/',
    'max-keys' => 50,
    'marker' => '',
);
try {
    $listObjectInfo = $ossClient->listObjects($bucket, $options);
} catch (OssException $e) {
    // 省略代码...
}

使用阿里云OSS作为文件服务器,需要有上传文件、列举文件列表、下载文件功能,当然你可以使用自己的数据库存储这些列表数据。个人建议,可以设置Referer防盗链,避免其他网站盗用你的图片,减少外网流出流量。

(5)在HTML中使用JavaScript上传文件到阿里云OSS

该小结是在2019-08-12补充的,主要为记录上次遗留的问题的解决方案:

1)如何方便快速的把整个站点上传到OSS,解决办法:图形化管理ossbrowser

2)如何在Web中直接上传或列举OSS上的文件。

在这个问题中,我看了阿里云OSS的文档,主要想突破Browser.js SDK的功能,Browser.js就是为了直接用客户端把文件上传至OSS而生。但是试了两天,存在的很多问题:STS权限问题、RAM控制问题(文档没说如何进入安全令牌<子账号授权>,后来工单咨询解决的,RAM权限控制都是json配置,配置了但是响应403,配置不对,基本不清楚到底要配置几个地方),依然没能解决。当时是提交工单问的,但是基本没有想要的回答,感觉工单客服人员都没用过,还要问后端工程师。

在工单后面的回答中,客服说可以直接使用WEB直传,这个也是sts临时授权,比较容易理解操作参考oss-h5-upload-js-direct

首先下了demo测试,这是经过POST上传的,和普通的表单提交一样。

问题:但该插件仍然不可列举某个目录下的文档。


总结:

(1)测试阿里OSS的下载速度达到 5-10M/s,完全达到各种下载需求。

(2)计费(标准型为例):数据存储,0.12元/GB/月;外网流出流量,0.5元/GB;如果使用CDN的话:CDN回源流出流量0.15元/GB;请求费用0.01元/万次

(3)应用场景:数据库备份选择归档存储类型,费用基本为0,要下载文件需要提前解冻;提供HTTP服务选择标准存储类型,例如提供静态Web服务、提供文件下载。

(4)使用阿里云OSS的好处:提供HTTP服务、下载网速快、价格便宜、安全性高、无需迁移、管理方便(不需要后台程序,可直接使用SDK管理)。

(5)遗留问题:如何方便快速的把整个站点上传到OSS,并且文件目录结构不变。

(6)缺点:文档复杂、授权过程复杂。

参考文章:

使用阿里云OSS+CDN部署前端页面与加速静态资源

配置静态网站托管

列举文件