diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 124b4b4d0..0293fad22 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -160,11 +160,11 @@ class ApiController extends Zend_Controller_Action // If we're passing in a Stored File object, it's faster // to use getFileSize() and pass in the result - if (!$size || $size <= 0) { + if (!isset($size) || $size < 0) { $size= filesize($location); } - if ($size <= 0) { + if ($size < 0) { throw new Exception("Invalid file size returned for file at $location"); } @@ -195,9 +195,11 @@ class ApiController extends Zend_Controller_Action header('Cache-Control: public, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Accept-Ranges: bytes'); - header('Content-Length:' . (($end - $begin) + 1)); - if (isset($_SERVER['HTTP_RANGE'])) { - header("Content-Range: bytes $begin-$end/$size"); + if ($size > 0) { + header('Content-Length:' . (($end - $begin) + 1)); + if (isset($_SERVER['HTTP_RANGE'])) { + header("Content-Range: bytes $begin-$end/$size"); + } } header("Content-Transfer-Encoding: binary"); diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index eb7825381..26cbea647 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -564,7 +564,10 @@ SQL; public function getFileSize() { $filesize = $this->_file->getFileSize(); - if ($filesize <= 0) { + + // It's OK for the file size to be zero. Pypo will make a request to Airtime and update + // the file size and md5 hash if they are not set. + if ($filesize < 0) { throw new Exception ("Could not determine filesize for file id: ".$this->_file->getDbId().". Filesize: ".$filesize); } return $filesize; diff --git a/python_apps/pypo/pypofile.py b/python_apps/pypo/pypofile.py index 58c3f91f3..630adfcbe 100644 --- a/python_apps/pypo/pypofile.py +++ b/python_apps/pypo/pypofile.py @@ -10,6 +10,9 @@ import sys import stat import requests import ConfigParser +import json +import hashlib +from requests.exceptions import ConnectionError, HTTPError, Timeout from std_err_override import LogWriter @@ -68,7 +71,6 @@ class PypoFile(Thread): host = config.get(CONFIG_SECTION, 'base_url') url = "http://%s/rest/media/%s/download" % (host, media_item["id"]) - with open(dst, "wb") as handle: response = requests.get(url, auth=requests.auth.HTTPBasicAuth(username, ''), stream=True, verify=False) @@ -85,11 +87,44 @@ class PypoFile(Thread): #make file world readable os.chmod(dst, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) + if media_item['filesize'] == 0: + file_size = self.report_file_size_and_md5_to_airtime(dst, media_item["id"], host, username) + media_item["filesize"] = file_size + media_item['file_ready'] = True except Exception, e: self.logger.error("Could not copy from %s to %s" % (src, dst)) self.logger.error(e) + def report_file_size_and_md5_to_airtime(self, file_path, file_id, host_name, api_key): + try: + file_size = os.path.getsize(file_path) + + with open(file_path, 'rb') as fh: + m = hashlib.md5() + while True: + data = fh.read(8192) + if not data: + break + m.update(data) + md5_hash = m.hexdigest() + except (OSError, IOError) as e: + file_size = 0 + self.logger.error("Error getting file size and md5 hash for file id %s" % file_id) + self.logger.error(e) + + # Make PUT request to Airtime to update the file size and hash + put_url = "http://%s/rest/media/%s" % (host_name, file_id) + payload = json.dumps({'filesize': file_size, 'md5': md5_hash}) + try: + response = requests.put(put_url, data=payload, auth=requests.auth.HTTPBasicAuth(api_key, '')) + if not response.ok: + self.logger.error("Could not update media file %s with file size and md5 hash" % file_id) + except (ConnectionError, Timeout): + self.logger.error("Could not update media file %s with file size and md5 hash" % file_id) + + return file_size + def get_highest_priority_media_item(self, schedule): """ Get highest priority media_item in the queue. Currently the highest