/** * Fill in the properties of this bitstream given its path. The file must * accessible by the web server. * * @deprecated * @throws Zend_Exception */ public function fillPropertiesFromPath() { // Check if the path exists if (!isset($this->path) || empty($this->path)) { throw new Zend_Exception('BitstreamDao path is not set in fillPropertiesFromPath()'); } // TODO: Compute the full path from the asset store. For now using the path. $this->setMimetype($this->Component->MimeType->getType($this->path)); // clear the stat cache, as the underlying file might have changed // since the last time filesize was called on the same filepath clearstatcache(); $this->setSizebytes(UtilityComponent::fileSize($this->path)); if (!isset($this->checksum) || empty($this->checksum)) { $this->setChecksum(UtilityComponent::md5file($this->path)); } }
/** * Calling this will stream the file to the client. * The parameter is a bitstream dao. * Optional second parameter is the download offset in bytes. * * @param BitstreamDao $bitstream * @param int $offset * @param bool $incrementDownload * @throws Zend_Exception */ public function download($bitstream, $offset = 0, $incrementDownload = false) { // Disable gzip output on apache servers (otherwise no progress in browser) if (function_exists('apache_setenv')) { apache_setenv('no-gzip', '1'); } $mimetype = $bitstream->getMimetype(); $path = $bitstream->getAssetstore()->getPath() . '/' . $bitstream->getPath(); $name = $bitstream->getName(); if (!file_exists($path)) { throw new Zend_Exception('Unable to find file on the disk'); } $chunkSize = 1024 * 64; $fileSize = UtilityComponent::fileSize($path); $handle = fopen($path, 'rb'); if ($handle === false) { throw new Zend_Exception('Unable to open the file'); } if (!$this->testingmode) { // don't send any headers in testing mode since it will break it $modified = gmdate('D, d M Y H:i:s') . ' GMT'; $contentType = $mimetype; header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Last-Modified: ' . $modified); // if pdf set the content-type accordingly if (!isset($contentType) && pathinfo($name, PATHINFO_EXTENSION) == 'pdf') { $contentType = 'application/pdf'; $enableContentDisposition = false; } if (!isset($contentType)) { $contentType = 'application/octet-stream'; } // Hack for .vsp files (for OSA) if (!isset($contentType) && strlen($name) > 4 && substr($name, strlen($name) - 4, 4) == '.vsp') { $contentType = 'application/isp'; } $agent = env('HTTP_USER_AGENT'); if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent) || preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) { header('Content-Type: ' . $contentType); header('Content-Disposition: attachment; filename="' . $name . '"'); header('Expires: 0'); header('Accept-Ranges: bytes'); header('Cache-Control: private', false); header('Pragma: private'); $httpRange = env('HTTP_RANGE'); if (isset($httpRange)) { // HTTP range is of the form "bytes=n-" where n is the offset list(, $range) = explode('=', $httpRange); $firstByte = strstr($range, '-', true); $lastByte = $fileSize - 1; $length = $fileSize - $firstByte; header('HTTP/1.1 206 Partial Content'); header('Content-Length: ' . $length); header('Content-Range: bytes ' . $firstByte . '-' . $lastByte . '/' . $fileSize); fseek($handle, $firstByte); } else { header('Content-Length: ' . $fileSize); } } else { header('Accept-Ranges: bytes'); header('Expires: 0'); header('Content-Type: ' . $contentType); header('Content-Length: ' . $fileSize); if (!isset($enableContentDisposition) || $enableContentDisposition == true) { header('Content-Disposition: attachment; filename="' . $name . '"'); } if (isset($httpRange)) { list(, $range) = explode('=', $httpRange); $firstByte = strstr($range, '-', true); $lastByte = $fileSize - 1; $length = $fileSize - $firstByte; header('HTTP/1.1 206 Partial Content'); header('Content-Length: ' . $length); header('Content-Range: bytes ' . $firstByte . '-' . $lastByte . '/' . $fileSize); fseek($handle, $firstByte); } } } ignore_user_abort(true); // must call this so the script doesn't end as soon as connection closed // close the database connection so we don't get too many connections problems Zend_Registry::get('dbAdapter')->closeConnection(); session_write_close(); // unlock session writing for concurrent access // kill the whole ob stack (Zend uses double nested output buffers) while (!$this->testingmode && ob_get_level() > 0) { ob_end_clean(); } if (is_numeric($offset) && $offset > 0 && $offset <= $fileSize) { fseek($handle, $offset); } while (!feof($handle) && connection_status() == 0) { echo fread($handle, $chunkSize); } if ($incrementDownload && feof($handle)) { // Only record downloads that actually complete /** @var ItemModel $itemModel */ $itemModel = MidasLoader::loadModel('Item'); $itemModel->incrementDownloadCount($bitstream->getItemrevision()->getItem()); } fclose($handle); if (!$this->testingmode) { // don't exit if we are in testing mode exit; } }
/** * Save new revision in the database. * * @param UserDao $userDao The user who is creating the revision * @param string $name The name of the file being used to create the revision * @param string $path * @param string $changes The changes comment by the user * @param int $itemId The item to create the new revision in * @param null|int $itemRevisionNumber [optional][default=null] Revision number for the item * @param null|int $license [optional][default=null] License text for the revision * @param string $fileChecksum [optional][default=''] If passed, will use it instead of calculating it ourselves * @param bool $copy [optional][default=false] If true, will copy the file. Otherwise it will just move it into the assetstore. * @param null|int $fileSize If passed, will use it instead of calculating it ourselves * @param null|string $mimeType If passed, will use it instead of calculating it ourselves * @return ItemDao * @throws Zend_Exception */ public function createNewRevision($userDao, $name, $path, $changes, $itemId, $itemRevisionNumber = null, $license = null, $fileChecksum = '', $copy = false, $fileSize = null, $mimeType = null) { if ($userDao === null) { throw new Zend_Exception('Please log in'); } /** @var ItemModel $itemModel */ $itemModel = MidasLoader::loadModel('Item'); $itemDao = $itemModel->load($itemId); if ($itemDao === false) { throw new Zend_Exception('Unable to find item'); } /** @var ItemRevisionModel $itemRevisionModel */ $itemRevisionModel = MidasLoader::loadModel('ItemRevision'); /** @var null|ItemRevisionDao $itemRevisionDao */ $itemRevisionDao = null; if (isset($itemRevisionNumber)) { $revisions = $itemDao->getRevisions(); foreach ($revisions as $revision) { if ($itemRevisionNumber == $revision->getRevision()) { $itemRevisionDao = $revision; break; } } } if (!$itemModel->policyCheck($itemDao, $userDao, MIDAS_POLICY_WRITE)) { throw new Zend_Exception('Parent permissions errors'); } if ($itemRevisionDao === null) { /** @var ItemRevisionDao $itemRevisionDao */ $itemRevisionDao = MidasLoader::newDao('ItemRevisionDao'); $itemRevisionDao->setChanges($changes); $itemRevisionDao->setUser_id($userDao->getKey()); $itemRevisionDao->setDate(date('Y-m-d H:i:s')); $itemRevisionDao->setLicenseId($license); $itemModel->addRevision($itemDao, $itemRevisionDao); } else { $itemRevisionDao->setChanges($changes); if ($license !== null) { $itemRevisionDao->setLicenseId($license); } $itemRevisionModel->save($itemRevisionDao); } /** @var BitstreamModel $bitstreamModel */ $bitstreamModel = MidasLoader::loadModel('Bitstream'); // Add bitstreams to the revision /** @var BitstreamDao $bitstreamDao */ $bitstreamDao = MidasLoader::newDao('BitstreamDao'); $bitstreamDao->setName($name); $bitstreamDao->setPath($path); if (empty($fileChecksum)) { $fileChecksum = UtilityComponent::md5file($path); } $bitstreamDao->setChecksum($fileChecksum); if (is_null($fileSize)) { $fileSize = UtilityComponent::fileSize($path); } $bitstreamDao->setSizebytes($fileSize); if (is_null($mimeType)) { /** @var MimeTypeComponent $mimeTypeComponent */ $mimeTypeComponent = MidasLoader::loadComponent('MimeType'); $mimeType = $mimeTypeComponent->getType($path, $name); } $bitstreamDao->setMimetype($mimeType); /** @var AssetstoreModel $assetStoreModel */ $assetStoreModel = MidasLoader::loadModel('Assetstore'); $assetStoreDao = $assetStoreModel->getDefault(); if ($assetStoreDao === false) { throw new Zend_Exception('Unable to load default asset store'); } $bitstreamDao->setAssetstoreId($assetStoreDao->getKey()); // Upload the bitstream if necessary (based on the asset store type) $this->uploadBitstream($bitstreamDao, $assetStoreDao, $copy); $checksum = $bitstreamDao->getChecksum(); $tmpBitstreamDao = $bitstreamModel->getByChecksum($checksum); if ($tmpBitstreamDao != false) { $bitstreamDao->setPath($tmpBitstreamDao->getPath()); $bitstreamDao->setAssetstoreId($tmpBitstreamDao->getAssetstoreId()); } $itemRevisionModel->addBitstream($itemRevisionDao, $bitstreamDao); // now that we have updated the itemRevision, the item may be stale $itemDao = $itemModel->load($itemId); $this->getLogger()->debug('Revision uploaded: [' . $bitstreamDao->getName() . '] into revision ' . $itemRevisionDao->getKey() . ' (item ' . $itemDao->getKey() . ')'); Zend_Registry::get('notifier')->notifyEvent('EVENT_CORE_UPLOAD_FILE', array($itemRevisionDao->getItem()->toArray(), $itemRevisionDao->toArray())); Zend_Registry::get('notifier')->callback('CALLBACK_CORE_UPLOAD_FILE', array($itemRevisionDao->getItem()->toArray(), $itemRevisionDao->toArray())); return $itemDao; }
/** * Get the amount of data already uploaded. * * @param array $args * @return array * @throws Exception */ public function getOffset($args) { // check parameters if (!array_key_exists($this->tokenParamName, $args)) { throw new Exception('Parameter ' . $this->tokenParamName . ' is not defined', MIDAS_HTTPUPLOAD_PARAM_UNDEFINED); } $uploadToken = $args[$this->tokenParamName]; $offset = UtilityComponent::fileSize(UtilityComponent::getTempDirectory() . '/' . $uploadToken); return array('offset' => $offset); }