Skip to content
This repository was archived by the owner on Sep 10, 2021. It is now read-only.

Commit 810c633

Browse files
committed
BUG: refs #974. ZipStream out of memory crash fix
We should now be able to zipstream stuff with any number of items and folders in it.
1 parent 5dd71f4 commit 810c633

File tree

3 files changed

+131
-81
lines changed

3 files changed

+131
-81
lines changed

core/controllers/DownloadController.php

Lines changed: 33 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,39 @@ public function indexAction()
235235
}
236236
ob_start();
237237
$zip = new ZipStream($name.'.zip');
238-
$zip = $this->_createZipRecursive($zip, '', $folders, $revisions, $sessionUser);
238+
foreach($revisions as $revision)
239+
{
240+
$item = $revision->getItem();
241+
$bitstreams = $revision->getBitstreams();
242+
$count = count($bitstreams);
243+
244+
foreach($bitstreams as $bitstream)
245+
{
246+
if($count > 1 || $bitstream->getName() != $item->getName())
247+
{
248+
$path = $item->getName().'/';
249+
}
250+
else
251+
{
252+
$path = '';
253+
}
254+
$filename = $path.$bitstream->getName();
255+
$fullpath = $bitstream->getAssetstore()->getPath().'/'.$bitstream->getPath();
256+
Zend_Registry::get('dbAdapter')->closeConnection();
257+
$zip->add_file_from_path($filename, $fullpath);
258+
}
259+
$this->Item->incrementDownloadCount($item);
260+
unset($item);
261+
unset($bitstreams);
262+
}
263+
foreach($folders as $folder)
264+
{
265+
if(!$this->Folder->policyCheck($folder, $sessionUser))
266+
{
267+
continue;
268+
}
269+
$this->Folder->zipStream($zip, $folder->getName(), $folder, $sessionUser);
270+
}
239271
$zip->finish();
240272
exit();
241273
}
@@ -464,57 +496,5 @@ private function _downloadEmptyItem($item)
464496
$zip->finish();
465497
exit();
466498
}
467-
468-
/** create zip recursive*/
469-
private function _createZipRecursive($zip, $path, $folders, $revisions, $sessionUser)
470-
{
471-
foreach($revisions as $revision)
472-
{
473-
$itemName = $revision->getItem()->getName();
474-
$bitstreams = $revision->getBitstreams();
475-
$count = count($bitstreams);
476-
477-
foreach($bitstreams as $bitstream)
478-
{
479-
if($count > 1 || $bitstream->getName() != $itemName)
480-
{
481-
$currPath = $path.'/'.$itemName;
482-
}
483-
else
484-
{
485-
$currPath = $path;
486-
}
487-
$filename = $currPath.'/'.$bitstream->getName();
488-
$fullpath = $bitstream->getAssetstore()->getPath().'/'.$bitstream->getPath();
489-
Zend_Registry::get('dbAdapter')->closeConnection();
490-
$zip->add_file_from_path($filename, $fullpath);
491-
}
492-
$this->Item->incrementDownloadCount($revision->getItem());
493-
}
494-
foreach($folders as $folder)
495-
{
496-
if(!$this->Folder->policyCheck($folder, $sessionUser))
497-
{
498-
continue;
499-
}
500-
$items = $folder->getItems();
501-
$subRevisions = array();
502-
foreach($items as $item)
503-
{
504-
$itemName = $item->getName();
505-
if(!$this->Item->policyCheck($item, $sessionUser))
506-
{
507-
continue;
508-
}
509-
$tmp = $this->Item->getLastRevision($item);
510-
if($tmp !== false)
511-
{
512-
$subRevisions[] = $tmp;
513-
}
514-
}
515-
$zip = $this->_createZipRecursive($zip, $path.'/'.$folder->getName(), $folder->getFolders(), $subRevisions, $sessionUser);
516-
}
517-
return $zip;
518-
}
519499
} // end class
520500

core/models/base/FolderModelBase.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ abstract function getSize($folder);
7070
abstract function getByName($name);
7171
abstract function getRecursiveChildCount($folder);
7272
abstract function getMaxPolicy($folderId, $user);
73+
abstract function zipStream(&$zip, $path, $folder, &$userDao);
7374

7475
/** Get the root folder */
7576
function getRoot($folder)

core/models/pdo/FolderModel.php

Lines changed: 97 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,32 @@ function getItemsFiltered($folder, $userDao = null, $policy = 0, $sortfield = 'n
704704
{
705705
$folderIds = array($folder->getKey());
706706
}
707+
708+
$sql = $this->_buildChildItemsQuery($userDao, $folderIds, $policy, $sortfield, $sortdir);
709+
710+
if($limit > 0)
711+
{
712+
$sql->limit($limit, $offset);
713+
}
714+
715+
$rowset = $this->database->fetchAll($sql);
716+
$return = array();
717+
foreach($rowset as $row)
718+
{
719+
$item = $this->initDao('Item', $row);
720+
$item->parent_id = $row['folder_id'];
721+
$return[] = $item;
722+
}
723+
return $return;
724+
}
725+
726+
/**
727+
* Helper function to build the child selection query
728+
* @param userDao The current user
729+
* @param folderIds Array of parent folder ids
730+
*/
731+
private function _buildChildItemsQuery(&$userDao, &$folderIds, $policy, $sortfield = 'name', $sortdir = 'asc')
732+
{
707733
$userId = $userDao instanceof UserDao ? $userDao->getKey() : -1;
708734
$isAdmin = $userDao instanceof UserDao ? $userDao->isAdmin() : false;
709735

@@ -737,21 +763,7 @@ function getItemsFiltered($folder, $userDao = null, $policy = 0, $sortfield = 'n
737763
->where('i.item_id IN ('.new Zend_Db_Expr($usrSql).') OR '.
738764
'i.item_id IN ('.new Zend_Db_Expr($grpSql).')');
739765
}
740-
741-
if($limit > 0)
742-
{
743-
$sql->limit($limit, $offset);
744-
}
745-
746-
$rowset = $this->database->fetchAll($sql);
747-
$return = array();
748-
foreach($rowset as $row)
749-
{
750-
$item = $this->initDao('Item', $row);
751-
$item->parent_id = $row['folder_id'];
752-
$return[] = $item;
753-
}
754-
return $return;
766+
return $sql;
755767
}
756768

757769
/**
@@ -776,6 +788,30 @@ function getChildrenFoldersFiltered($folder, $userDao = null, $policy = 0, $sort
776788
{
777789
$folderIds = array($folder->getKey());
778790
}
791+
792+
$sql = $this->_buildChildFoldersQuery($userDao, $folderIds, $policy, $sortfield, $sortdir);
793+
794+
if($limit > 0)
795+
{
796+
$sql->limit($limit, $offset);
797+
}
798+
799+
$rowset = $this->database->fetchAll($sql);
800+
$return = array();
801+
foreach($rowset as $row)
802+
{
803+
$return[] = $this->initDao('Folder', $row);
804+
}
805+
return $return;
806+
}
807+
808+
/**
809+
* Helper function to build the child selection query
810+
* @param userDao The current user
811+
* @param folderIds Array of parent folder ids
812+
*/
813+
private function _buildChildFoldersQuery(&$userDao, &$folderIds, $policy, $sortfield = 'name', $sortdir = 'asc')
814+
{
779815
$userId = $userDao instanceof UserDao ? $userDao->getKey() : -1;
780816
$isAdmin = $userDao instanceof UserDao ? $userDao->isAdmin() : false;
781817

@@ -807,19 +843,7 @@ function getChildrenFoldersFiltered($folder, $userDao = null, $policy = 0, $sort
807843
->where('f.folder_id IN ('.new Zend_Db_Expr($usrSql).') OR '.
808844
'f.folder_id IN ('.new Zend_Db_Expr($grpSql).')');
809845
}
810-
811-
if($limit > 0)
812-
{
813-
$sql->limit($limit, $offset);
814-
}
815-
816-
$rowset = $this->database->fetchAll($sql);
817-
$return = array();
818-
foreach($rowset as $row)
819-
{
820-
$return[] = $this->initDao('Folder', $row);
821-
}
822-
return $return;
846+
return $sql;
823847
}
824848

825849
/** Get the child folder
@@ -1020,6 +1044,51 @@ function isDeleteable($folder)
10201044
return true;
10211045
}
10221046

1047+
/**
1048+
* This will zip stream the filtered contents of the fold
1049+
*/
1050+
public function zipStream(&$zip, $path, $folder, &$userDao)
1051+
{
1052+
$folderIds = array($folder->getKey());
1053+
$this->Item = MidasLoader::loadModel('Item');
1054+
1055+
$sql = $this->_buildChildItemsQuery($userDao, $folderIds, MIDAS_POLICY_READ);
1056+
$rows = $this->database->fetchAll($sql);
1057+
foreach($rows as $row)
1058+
{
1059+
$item = $this->initDao('Item', $row);
1060+
$bitstreams = $this->Item->getLastRevision($item)->getBitstreams();
1061+
$count = count($bitstreams);
1062+
1063+
foreach($bitstreams as $bitstream)
1064+
{
1065+
if($count > 1 || $bitstream->getName() != $item->getName())
1066+
{
1067+
$currPath = $path.'/'.$item->getName().'/'.$bitstream->getName();
1068+
}
1069+
else
1070+
{
1071+
$currPath = $path.'/'.$bitstream->getName();
1072+
}
1073+
$zip->add_file_from_path($currPath, $bitstream->getAssetstore()->getPath().'/'.$bitstream->getPath());
1074+
}
1075+
$this->Item->incrementDownloadCount($item);
1076+
unset($bitstreams);
1077+
unset($item);
1078+
}
1079+
unset($sql);
1080+
unset($rows);
1081+
1082+
$sql = $this->_buildChildFoldersQuery($userDao, $folderIds, MIDAS_POLICY_READ);
1083+
$rows = $this->database->fetchAll($sql);
1084+
foreach($rows as $row)
1085+
{
1086+
$subfolder = $this->initDao('Folder', $row);
1087+
$this->zipStream($zip, $path.'/'.$subfolder->getName(), $subfolder, $userDao);
1088+
unset($subfolder);
1089+
}
1090+
}
1091+
10231092
/**
10241093
* Will return all root folder daos. There is a root folder for each
10251094
* user, and one for each community.

0 commit comments

Comments
 (0)