#!/usr/bin/env python3 # -*- coding: utf-8 -*- import hashlib import logging import math import os import requests import time from .resource import API_URLS, Resource logger = logging.getLogger('pod_client.resource') class PodClient: host_url = '' api_key = '' def __init__(self, host_url, api_key, site_id=1): self.host_url = host_url if not self.host_url: raise Exception('Pod host url required') self.api_key = api_key if not self.api_key: raise Exception('Pod api key required') for resource_name in API_URLS.keys(): self.__dict__[resource_name] = Resource(self.host_url, self.api_key, resource_name, site_id) def chunked_upload(self, file_path, slug=None, progress_callback=None, progress_data=None, check_md5=True, timeout=3600): url_prefix = '%s/api/' % self.host_url chunk_size = 1000000 total_size = os.path.getsize(file_path) chunks_count = math.ceil(total_size / chunk_size) chunk_index = 0 start_offset = 0 end_offset = min(chunk_size, total_size) - 1 data = dict() if check_md5: md5sum = hashlib.md5() begin = time.time() with open(file_path, 'rb') as file_object: while True: chunk = file_object.read(chunk_size) if not chunk: break chunk_index += 1 logger.debug('Uploading chunk %s/%s.', chunk_index, chunks_count) if check_md5: md5sum.update(chunk) files = {'file': (os.path.basename(file_path), chunk)} headers = {'Content-Range': 'bytes %s-%s/%s' % (start_offset, end_offset, total_size)} response = requests.request('post', url_prefix + 'chunked_upload/', data=data, files=files, headers=headers, timeout=timeout) if response.status_code != 200: raise Exception('Error {status_code}: "{text}"'.format(status_code=response.status_code, text=response.text)) response = response.json() if progress_callback: pdata = progress_data or dict() progress_callback(0.9 * end_offset / total_size, **pdata) if 'upload_id' not in data: data['upload_id'] = response['upload_id'] start_offset += chunk_size end_offset = min(end_offset + chunk_size, total_size - 1) bandwidth = total_size * 8 / ((time.time() - begin) * 1000000) logger.debug('Upload finished, average bandwidth: %.2f Mbits/s', bandwidth) if check_md5: data['md5'] = md5sum.hexdigest() else: data['no_md5'] = 'yes' if slug: data['slug'] = slug requests.request('post', url_prefix + 'chunked_upload/complete/', data=data, timeout=timeout) if progress_callback: pdata = progress_data or dict() progress_callback(1., **pdata) return data['upload_id']