Python 上传文件-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

Python 上传文件

2017-12-16 03:15:01 890
Python
分享到
取消 提交回答
全部回答(1)
  • 2017-12-17 17:56:03
    已采纳

    详细解答可以参考官方帮助文档

    在OSS中,操作的基本数据单元是文件(Object)。OSS Python SDK提供了丰富的文件上传方式:

    • 简单上传:文件最大不能超过5GB。
    • 追加上传:文件最大不能超过5GB。
    • 断点续传上传:支持并发、断点续传、自定义分片大小。大文件上传推荐使用断点续传。最大不能超过48.8TB。
    • 分片上传:当文件较大时,可以使用分片上传,最大不能超过48.8TB。

    说明:各种上传方式的适用场景请参见开发指南中的上传文件。

    上传过程中,您还可以通过进度条功能查看上传进度。上传完成后,您还可以进行上传回调

    简单上传

    通过bucket.put_object方法上传文件。上传方法支持多种类型的输入源,输入源有如下几种类型:

    类型 上传方式
    字符串 直接上传
    Bytes 直接上传
    Unicode 自动转换为UTF-8编码的Bytes进行上传
    本地文件 文件对象(File Object),必须以二进制方式打开(如“rb”模式)
    网络流 可迭代对象(Iterable),以Chunked Encoding的方式上传

    上传字符串

    以下代码用于上传字符串:

    1. # -*- coding: utf-8 -*-
    2. import oss2
    3. # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    4. auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
    5. # Endpoint以杭州为例,其它Region请按实际情况填写。
    6. bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
    7. # 返回值。
    8. result = bucket.put_object('<yourObjectName>', 'content of object')
    9. # HTTP返回码。
    10. print('http status: {0}'.format(result.status))
    11. # 请求ID。请求ID是请求的唯一标识,强烈建议在程序日志中添加此参数。
    12. print('request_id: {0}'.format(result.request_id))
    13. # ETag是put_object方法返回值特有的属性。
    14. print('ETag: {0}'.format(result.etag))
    15. # HTTP响应头部。
    16. print('date: {0}'.format(result.headers['date']))

    上传Bytes

    以下代码用于上传Bytes:

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

    上传Unicode

    以下代码用于上传Unicode:

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

    上传本地文件

    以下代码用于上传本地文件:

    1. # -*- coding: utf-8 -*-
    2. import oss2
    3. # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    4. auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
    5. # Endpoint以杭州为例,其它Region请按实际情况填写。
    6. bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
    7. # 必须以二进制的方式打开文件,因为需要知道文件包含的字节数。
    8. with open('<yourLocalFile>', 'rb') as fileobj:
    9. # Seek方法用于指定从第1000个字节位置开始读写。上传时会从您指定的第1000个字节位置开始上传,直到文件结束。
    10. fileobj.seek(1000, os.SEEK_SET)
    11. # Tell方法用于返回当前位置。
    12. current = fileobj.tell()
    13. bucket.put_object('<yourObjectName>', fileobj)

    Python SDK还提供了一个更加便捷的方法用于上传本地文件:

    1. bucket.put_object_from_file('<yourObjectName>', '<yourLocalFile>')

    上传网络流

    以下代码用于上传网络流:

    1. # -*- coding: utf-8 -*-
    2. import oss2
    3. import requests
    4. # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    5. auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
    6. # Endpoint以杭州为例,其它Region请按实际情况填写。
    7. bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
    8. # requests.get返回的是一个可迭代对象(Iterable),此时Python SDK会通过Chunked Encoding方式上传。
    9. input = requests.get('http://www.aliyun.com')
    10. bucket.put_object('<yourObjectName>', input)

    追加上传

    以下代码用于追加上传文件:

    1. # -*- coding: utf-8 -*-
    2. import oss2
    3. # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    4. auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
    5. # Endpoint以杭州为例,其它Region请按实际情况填写。
    6. bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
    7. # 设置首次上传的追加位置(Position参数)为0。
    8. result = bucket.append_object('<yourObjectName>', 0, 'content of first append')
    9. # 如果不是首次上传,可以通过bucket.head_object方法或上次追加返回值的next_position属性,得到追加位置。
    10. bucket.append_object('<yourObjectName>', result.next_position, 'content of second append')

    如果文件已经存在,如下两种情况将会抛出异常:

    • 不是可追加文件,则抛出ObjectNotAppendable异常。
    • 是可追加文件,但设置的追加位置和文件当前长度不等,则抛出PositionNotEqualToLength异常。

    断点续传上传

    断点续传上传将要上传的文件分成若干个分片(Part)分别上传,所有分片都上传完成后,将所有分片合并成完整的文件,完成整个文件的上传。

    您可以通过oss2.resumable_upload方法断点续传上传指定文件,该方法包含以下参数:

    参数 描述 是否必需 默认值
    bucket 存储空间名称
    key 文件名称
    filename 待上传的本地文件名称
    store 指定保存断点信息的目录 HOME目录下建立的.py-oss-upload目录
    headers HTTP头部
    multipart_threshold 文件长度大于该值时,则用分片上传 10MB
    part_size 分片大小 自动计算
    progress_callback 上传进度回调函数
    num_threads 并发上传的线程数 1

    以下代码用于断点续传上传:

    1. # -*- coding: utf-8 -*-
    2. import oss2
    3. # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    4. auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
    5. # Endpoint以杭州为例,其它Region请按实际情况填写。
    6. bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
    7. # 当文件长度大于或等于可选参数multipart_threshold(默认值为10MB)时,会使用分片上传。如未使用参数store指定目录,则会在HOME目录下建立.py-oss-upload目录来保存断点信息。
    8. oss2.resumable_upload(bucket, '<yourObjectName>', '<yourLocalFile>')

    Python SDK 2.1.0以上版本支持设置可选参数进行断点续传上传,代码如下:

    1. # 如使用store指定了目录,则保存断点信息在指定目录中。如使用num_threads设置上传并发数,请将oss2.defaults.connection_pool_size设成大于或等于线程数。默认线程数为1。
    2. oss2.resumable_upload(bucket, '<yourObjectName>', '<yourLocalFile>',
    3. store=oss2.ResumableStore(root='/tmp'),
    4. multipart_threshold=100*1024,
    5. part_size=100*1024,
    6. num_threads=4)

    断点续传详情请参见开发指南中的断点续传

    分片上传

    分片上传(Multipart Upload)分为以下三个步骤:

    • 初始化(bucket.init_multipart_upload):获得Upload ID。
    • 上传分片(bucket.upload_part):上传分片数据。这一步可以并发进行。
    • 完成上传(bucket.complete_multipart_upload):所有分片上传完成后,合并分片,生成OSS文件。

    以下代码用于分片上传文件:

    1. # -*- coding: utf-8 -*-
    2. import os
    3. from oss2 import SizedFileAdapter, determine_part_size
    4. from oss2.models import PartInfo
    5. import oss2
    6. # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    7. auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
    8. # Endpoint以杭州为例,其它Region请按实际情况填写。
    9. bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
    10. key = '<yourObjectName>'
    11. filename = '<yourLocalFile>'
    12. total_size = os.path.getsize(filename)
    13. # determine_part_size方法用来确定分片大小。
    14. part_size = determine_part_size(total_size, preferred_size=100 * 1024)
    15. # 初始化分片。
    16. upload_id = bucket.init_multipart_upload(key).upload_id
    17. parts = []
    18. # 逐个上传分片。
    19. with open(filename, 'rb') as fileobj:
    20. part_number = 1
    21. offset = 0
    22. while offset < total_size:
    23. num_to_upload = min(part_size, total_size - offset)
    24. # SizedFileAdapter(fileobj, size)方法会生成一个新的文件对象,重新计算起始追加位置。
    25. result = bucket.upload_part(key, upload_id, part_number,
    26. SizedFileAdapter(fileobj, num_to_upload))
    27. parts.append(PartInfo(part_number, result.etag))
    28. offset += num_to_upload
    29. part_number += 1
    30. # 完成分片上传。
    31. bucket.complete_multipart_upload(key, upload_id, parts)
    32. # 验证分片上传。
    33. with open(filename, 'rb') as fileobj:
    34. assert bucket.get_object(key).read() == fileobj.read()

    进度条

    进度条用于指示上传或下载的进度。下面的代码以bucket.put_object方法为例,介绍如何使用进度条。

    1. # -*- coding: utf-8 -*-
    2. from __future__ import print_function
    3. import os, sys
    4. import oss2
    5. # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    6. auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
    7. # Endpoint以杭州为例,其它Region请按实际情况填写。
    8. bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
    9. # 当无法确定待上传的数据长度时,total_bytes的值为None。
    10. def percentage(consumed_bytes, total_bytes):
    11. if total_bytes:
    12. rate = int(100 * (float(consumed_bytes) / float(total_bytes)))
    13. print('\r{0}% '.format(rate), end='')
    14. sys.stdout.flush()
    15. # progress_callback为可选参数,用于实现进度条功能。
    16. bucket.put_object('<yourObjectName>', 'a'*1024*1024, progress_callback=percentage)

    进度条的完整示例代码请参见GitHub

    上传回调

    以下代码用于上传回调:

    1. # -*- coding: utf-8 -*-
    2. import json
    3. import base64
    4. import os
    5. import oss2
    6. # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    7. auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
    8. # Endpoint以杭州为例,其它Region请按实际情况填写。
    9. bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
    10. # 准备回调参数。
    11. callback_dict = {}
    12. # 设置回调请求的服务器地址,如http://oss-demo.aliyuncs.com:23450或http://127.0.0.1:9090。
    13. callback_dict['callbackUrl'] = 'http://oss-demo.aliyuncs.com:23450'
    14. # 设置回调请求消息头中Host的值, 如oss-cn-hangzhou.aliyuncs.com。
    15. callback_dict['callbackHost'] = 'oss-cn-hangzhou.aliyuncs.com'
    16. # 设置发起回调时请求body的值。
    17. callback_dict['callbackBody'] = 'filename=${object}&size=${size}&mimeType=${mimeType}'
    18. # 设置发起回调请求的Content-Type。
    19. callback_dict['callbackBodyType'] = 'application/x-www-form-urlencoded'
    20. # 回调参数是Json格式,并且需要Base64编码。
    21. callback_param = json.dumps(callback_dict).strip()
    22. base64_callback_body = base64.b64encode(callback_param)
    23. # 回调参数编码后放在Header中发送给OSS。
    24. headers = {'x-oss-callback': base64_callback_body}
    25. # 上传并回调。
    26. result = bucket.put_object('<yourObjectName>', 'a'*1024*1024, headers)

    put_object、put_object_from_file、complete_multipart_upload支持上传回调功能。上传回调的详细说明请参见API参考中的上传回调。上传回调的完整示例代码请参见GitHub

    0 0
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

推荐文章
相似问题
推荐课程