OSS大文件断点续传下载

922 阅读2分钟

ali-oss没有提供node版本断点续传下载的sdk,于是使用python的sdk写了两个接口:1.断点续传下载 2.获取下载进度。

写在前面:

chrome浏览器的下载管理器就能够实现断点续传下载,但是200G的文件需要十几个小时,时间非常久且网速关系密切。如在业务中大文件下载建议使用百度网盘或其他工具,此处仅作为学习。

代码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import flask
import json
from flask import request, Flask
import flask_cors
import os
import sys
import oss2
from functools import wraps
progress = 0
'''
flask: seb框架,通过flask提供的装饰器@server.route()将普通函数转换为服务
登录接口,需要传入url,username,passwd
'''

# 创建一个服务,把当前这个python文件当做一个服务
server = flask.Flask(__name__)
flask_cors.CORS(server, supports_credentials=True)  # 设置参数
# server.route()可以将普通函数转变为服务 登录接口的路径、请求方式


def allow_cross_domain(fun):
    @wraps(fun)
    def wrapper_fun(*args, **kwargs):
        rst = make_response(fun(*args, **kwargs))
        rst.headers['Access-Control-Allow-Origin'] = '*'
        rst.headers['Access-Control-Allow-Methods'] = 'PUT,GET,POST,DELETE'
        allow_headers = "Referer,Accept,Origin,User-Agent"
        rst.headers['Access-Control-Allow-Headers'] = allow_headers
        return rst
    return wrapper_fun


@allow_cross_domain
def domains():
    pass


def percentage(consumed_bytes, total_bytes):
    global progress
    if total_bytes:
        rate = "%.6f" % (float(consumed_bytes) / float(total_bytes))
        progress = rate
        print('\r{0} '.format(rate), end='')
        sys.stdout.flush()


@server.route('/getProgress', methods=['get'])
def getProgress():
    resu = {'code': 1, 'data': progress}
    return json.dumps(resu, ensure_ascii=False)


@server.route('/ossDownload', methods=['post'])
def ossDownload():

    filename = request.values.get('name')
    url = request.values.get('url')
    path = request.values.get('path')

    auth = oss2.Auth('xxxxxxxxxxx',           #此处替换为你项目中具体的,下同
                     'xxxxxxxxxxx')
    bucket = oss2.Bucket(
        auth, 'http://xxxxxxxxxxx.com', 'xxxxxxxxxxx')
    #'bucket','<yourObjectName>', '<yourLocalFile>'
    # <yourObjectName>从OSS下载文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
    # <yourLocalFile>由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt。
    # 请将oss2.defaults.connection_pool_size设成大于或等于线程数,并将part_size参数设成大于或等于oss2.defaults.multiget_part_size。

    oss2.resumable_download(bucket, url, path + '/' + filename,
                            store=oss2.ResumableDownloadStore(
                                root=path),
                            multiget_threshold=20*1024*1024,
                            part_size=20*1024*1024,
                            num_threads=3,
                            progress_callback=percentage)

    resu = {'code': 1, 'message': '下载完成'}
    return json.dumps(resu, ensure_ascii=False)

if __name__ == '__main__':
    # 指定端口,host,0.0.0.0代表不管几个网卡,任何ip都可访问python
    # 测试环境
    server.run(debug=True, port=8099, host='0.0.0.0')
    # 生产环境
    # app = pywsgi.WSGIServer(('0.0.0.0', 8099), server)
    # app.serve_forever()

启动

执行python3 server.py

注意警告部分:这里启动服务的时候是debug模式,即测试环境。

调用

1.下载

 multiDownload() {
    let url = item.url.slice(index + 5); //待下载的文件的地址
    let name = item.name.substr(item.name.lastIndexOf("/") + 1); //文件名
    let path = this.downloadPath; //要保存在本地的路径,为绝对路径
    this.$axios.post("http://xxxxxx:8099//ossDownload?name=" +
      name + "&url=" + url + "&path=" + path, {}).then(res => {
        if (res.data.code === 1) {
          this.success(res.data.message);
        }
      }).catch(err => {
        this.error("下载出错");
      });
  },

2.获取进度

getProgress() {
  this.$axios.get("http://xxxxxx:8099/getProgress")
  .then(res => {
  }).catch(err => {
  });
},