getPropelOrm()->isValidPhysicalFile()) { $filename = $media->getPropelOrm()->getFilename(); // Download user left clicks a track and selects Download. if (!$inline) { // We are using Content-Disposition to specify // to the browser what name the file should be saved as. header('Content-Disposition: attachment; filename="' . $filename . '"'); } else { // user clicks play button for track and downloads it. header('Content-Disposition: inline; filename="' . $filename . '"'); } /* In this block of code below, we're getting the list of download URLs for a track and then streaming the file as the response. A file can be stored in more than one location, with the alternate locations used as a fallback, so that's why we're looping until we are able to actually send the file. This mechanism is used to try fetching our file from our internal S3 caching proxy server first. If the file isn't found there (or the cache is down), then we attempt to download the file directly from Amazon S3. We do this to save bandwidth costs! */ $filePaths = $media->getFilePaths(); assert(is_array($filePaths)); do { // Read from $filePath and stream it to the browser. $filePath = array_shift($filePaths); try { $size = $media->getFileSize(); $mimeType = $media->getPropelOrm()->getDbMime(); Application_Common_FileIO::smartReadFile($filePath, $size, $mimeType); break; // Break out of the loop if we successfully read the file! } catch (LibreTimeFileNotFoundException $e) { // If we have no alternate filepaths left, then let the exception bubble up. if (count($filePaths) == 0) { throw $e; } } // Retry with the next alternate filepath in the list } while (count($filePaths) > 0); exit; } throw new LibreTimeFileNotFoundException($filePath); } /** * Check if there are any files that have been stuck * in Pending status for over an hour. * * @return bool true if there are any files stuck pending, * otherwise false */ public static function areFilesStuckInPending() { $oneHourAgo = gmdate(DEFAULT_TIMESTAMP_FORMAT, microtime(true) - self::PENDING_FILE_TIMEOUT_SECONDS); self::$_pendingFiles = CcFilesQuery::create() ->filterByDbImportStatus(CcFiles::IMPORT_STATUS_PENDING) ->filterByDbUtime($oneHourAgo, Criteria::LESS_EQUAL) ->find(); $pendingEpisodes = Application_Service_PodcastEpisodeService::getStuckPendingImports(); return !self::$_pendingFiles->isEmpty() || !empty($pendingEpisodes); } /** * Clean up stuck imports by changing their import status to Failed. */ public static function clearStuckPendingImports() { $pendingEpisodes = Application_Service_PodcastEpisodeService::getStuckPendingImports(); foreach (self::$_pendingFiles as $file) { // @var $file CcFiles $file->setDbImportStatus(CcFiles::IMPORT_STATUS_FAILED)->save(); } foreach ($pendingEpisodes as $episode) { // @var $episode PodcastEpisodes $episode->delete(); } } }