from requests import post, delete from json import loads from models import Video from os import stat CHUNK_SIZE = 5 * 1024 * 1024 class UploadSession(object): def __init__(self, panda, file_name, **kwargs): self.panda = panda self.file_name = file_name self.file_size = stat(file_name).st_size params = { "file_size": self.file_size, "file_name": file_name, "profiles": "h264" } params.update(kwargs) data = panda.post('/videos/upload.json', params) self.location = loads(data)["location"] self.status = "initialized" self.video = None self.error_message = None def _read_chunks(self, file_object): i = 0 while True: data = file_object.read(CHUNK_SIZE) if not data: break yield (data, i) i = i+1 def start(self, pos=0): if self.status == "initialized": self.status = "uploading" with open(self.file_name) as f: f.seek(pos) try: for chunk, i in self._read_chunks(f): index = i * CHUNK_SIZE res = post(self.location, headers = { 'Content-Type': 'application/octet-stream', 'Cache-Control': 'no-cache', 'Content-Range': "bytes {0}-{1}/{2}".format(pos+index, pos+index+CHUNK_SIZE-1, self.file_size), 'Content-Length': str(CHUNK_SIZE) }, data=chunk) if res.status_code == 200: self.status = "uploaded" self.video = Video(self.panda, json_attr=res.json()) elif res.status_code != 204: self.status = "error" break except Exception as e: self.status = "error" self.error_message = str(e) raise e except KeyboardInterrupt: self.status = "error" self.error_message = "interrupted" else: raise KeyError("Already started") def resume(self): if self.status != "uploaded": res = post(self.location, headers = { 'Content-Type': 'application/octet-stream', 'Cache-Control': 'no-cache', 'Content-Range': "bytes */{0}".format(self.file_size), 'Content-Length': "0" }) pos = int(res.headers["Range"].split("-")[1]) self.status = "initialized" self.start(pos=pos) else: raise KeyError("Already succeed") def abort(self): if self.status != "success": self.status = "aborted" self.error_message = None res = delete(self.location) else: raise KeyError("Already succeed")