树莓派ZeroW上传数据文件到阿里云对象存储OSS(Python)

>> [目录] 数据远程采集 Step by Step


树莓派型号:Zero W

树莓派系统:Raspbian,2018-11-13-raspbian-stretch-lite.img

SD卡:闪迪32G class10 高速Micro SD卡(TF卡)

存储工具:阿里云->对象存储



阿里云的SDK文档(有各种语言的版本,这里选的是Python),提供了上传数据的样例程序:

https://help.aliyun.com/document_detail/32027.html?spm=a2c4g.11186623.2.24.5c741c62a5XKqp#concept-32027-zh

# -*- coding: utf-8 -*-
import oss2

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

# <yourObjectName>上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
# <yourLocalFile>由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt。
bucket.put_object_from_file('<yourObjectName>', '<yourLocalFile>')


功能需求


间隔一段时间扫描一次<待上传>目录,如果该目录下有数据文件,就将第一个文件上传到对象存储指定bucket(考虑到以后会有几十台数据采集装置,为了便于管理,每个装置在bucket上有一个专属的二级子目录),上传成功后将这个文件移动到<已上传>目录下。


环境准备


手动创建两个工作目录,分别用于存放<待上传>和<已上传>的数据文件:

mkdir -p ~/project/data/updating

mkdir -p ~/project/data/updated


updating目录下用touch指令创建一个测试文件test.db:

pi@raspberrypi:~ $ cd ~/project/data/updating

pi@raspberrypi:~/project/data/updating $ touch test.db

image


程序文件


切换到主目录下,创建test_upload.py文件,复制内容进去,保存退出

注意:<yourAccessKeyId>、<yourAccessKeySecret>、<yourBucketName>要改成自己的

pi@raspberrypi:~/project/data/updating $ cd ~

pi@raspberrypi:~ $ sudo nano test_upload.py

  1 # -*- coding: utf-8 -*-
  2 import os
  3 import time
  4 import shutil
  5 import oss2
  6 import ConfigParser
  7 
  8 PRODUCT_TYPE = 'NULL'
  9 DEVICE_ID = 999 #default
 10 
 11 #----
 12 def UploadFile_oss2(localfile):
 13   global PRODUCT_TYPE
 14   global DEVICE_ID
 15 
 16   access_key = '<yourAccessKeyId>'
 17   secret_key = '<yourAccessKeySecret>'
 18 
 19   try:
 20     auth = oss2.Auth(access_key, secret_key)
 21     bucket = oss2.Bucket(auth, 'oss-cn-beijing.aliyuncs.com', '<yourBucketName>')
 22 
 23     # 文件是否存在
 24     print '>> uploading local file: ' + localfile
 25     if False == os.path.exists(localfile):
 26       print '>> local file not exist: ' + localfile
 27       return False
 28 
 29     # 根据产品类型、树莓派编号,生成二级目录
 30     objectname = PRODUCT_TYPE + '_' + str(DEVICE_ID).rjust(3,'0') \
 31                  + '/' + os.path.basename(localfile)
 32     print '>> upload result...'
 33     result = bucket.put_object_from_file(objectname, localfile)
 34 
 35     print result
 36 
 37     # result.status 200 表示上传成功
 38     if result.status == 200:
 39       return True
 40     else:
 41       return False
 42   except:
 43     return False
 44 
 45 #----
 46 def UploadFile(localfile):
 47   return UploadFile_oss2(localfile)
 48 
 49 #----
 50 def main():
 51   global PRODUCT_TYPE
 52   global DEVICE_ID
 53 
 54   DB_UPDATING_DIR = '/home/pi/project/data/updating/'
 55   DB_UPDATED_DIR  = '/home/pi/project/data/updated/'
 56   CONFIG_FILE     = '/home/pi/project/config.ini'
 57   file_path       = ''
 58 
 59   # time.sleep(10)
 60   # 读取产品类型、树莓派编号
 61   GetDeviceInfo(CONFIG_FILE)
 62 
 63   print '>> uploading scheduler start...'
 64   while True:
 65     filelist = os.listdir(DB_UPDATING_DIR)
 66     if len(filelist) > 0:
 67       # 获得<待上传>文件夹下的第一个数据文件
 68       file_path = os.path.join(DB_UPDATING_DIR, filelist[0])
 69       if os.path.exists(file_path):
 70         print '>> file need upload: ' + file_path
 71         if True == UploadFile(file_path):
 72           # 上传成功,将数据文件放到<已上传>文件夹中
 73           MoveFile(file_path, DB_UPDATED_DIR)
 74           print '>> upload succeed: '+ file_path
 75 
 76     # 每隔一段时间扫描一次<待上传>文件夹(每小时生成一个新的数据文件)
 77     time.sleep(30)
 78 
 79 #----
 80 def GetDeviceInfo(file_path):
 81   global PRODUCT_TYPE
 82   global DEVICE_ID
 83 
 84   # 读取配置信息
 85   PRODUCT_TYPE = 'NULL'
 86   DEVICE_ID = 999
 87   '''
 88   try:
 89     config = ConfigParser.ConfigParser()
 90     config.read(file_path)
 91     if "device" in config.sections():
 92       PRODUCT_TYPE = config.get("device", "type")
 93       DEVICE_ID    = config.getint("device", "id")
 94   except:
 95     # 配置文件加载异常,使用默认参数:产品类型NULL 树莓派编号999
 96     PRODUCT_TYPE = 'NULL'
 97     DEVICE_ID = 999
 98   '''
 99 
100 #----
101 def MoveFile(src_file_path, dst_folder_path):
102   try:
103     if not os.path.exists(dst_folder_path):
104       os.mkdir(dst_folder_path)
105     shutil.move(src_file_path, dst_folder_path)
106   except:
107     return
108 
109 #----
110 if __name__ == '__main__':
111   main()


>> def UploadFile_oss2(localfile):

这个函数把本地文件上传到阿里云对象存储的buckek空间。

基本是按照官方提供的样例程序写的,加了一些防止异常的冗余代码。

上传时使用二次子目录,直接在objectname加上目录就可以了

objectname = 'NULL_999/' + os.path.basename(localfile)

上传结果result.status为200表示上传成功。


>> def UploadFile(localfile):

调用UploadFile_oss2,隔离一下,万一要改成其他云。


>> def GetDeviceInfo(file_path):

获取设备信息:产品信号、设备编号,每个设备根据这个信息,可以在bucket空间上创建专属的二级子目录,便于管理数据。

这些设置信息保存在一个配置文件中,用ConfigParser库进行访问,为了简化操作现在这段代码暂时注释掉了,直接使用默认的设备信息。


>> def MoveFile(src_file_path, dst_folder_path):

文件上传成功后,从<待上传>移动到<已上传>。

如果目标目录不存在,使用os库创建该目录;使用shutil库进行文件移动操作。


>> def main():

间隔一段时间扫描一次<待上传>目录,上传该目录下的第一个文件。

filelist = os.listdir(DB_UPDATING_DIR),获得该目录下的文件清单

os.path.join(DB_UPDATING_DIR, filelist[0]),获得第一个文件的路径


运行测试


运行test_upload.py,显示数据上传成功

pi@raspberrypi:~ $ python test_upload.py

image

切换到updated目录下,文件已经移动过来了

pi@raspberrypi:~ $ cd ~/project/data/updated

pi@raspberrypi:~/project/data/updated $ ls

image

打开阿里云app,管控->文件管理->xxxx_bucket_name,多了一个NULL_999的二级目录,进入该目录,test.db文件已经上传成功了。

image

posted @ 2020-04-22 14:21  hotwater99  阅读(1042)  评论(0编辑  收藏  举报