preview.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. <?php
  2. /**
  3. * Copyright (c) 2013 Frank Karlitschek frank@owncloud.org
  4. * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
  5. * This file is licensed under the Affero General Public License version 3 or
  6. * later.
  7. * See the COPYING-README file.
  8. *
  9. * Thumbnails:
  10. * structure of filename:
  11. * /data/user/thumbnails/pathhash/x-y.png
  12. *
  13. */
  14. namespace OC;
  15. use OC\Preview\Provider;
  16. use OCP\Files\FileInfo;
  17. use OCP\Files\NotFoundException;
  18. class Preview {
  19. //the thumbnail folder
  20. const THUMBNAILS_FOLDER = 'thumbnails';
  21. //config
  22. private $maxScaleFactor;
  23. private $configMaxX;
  24. private $configMaxY;
  25. //fileview object
  26. private $fileView = null;
  27. private $userView = null;
  28. //vars
  29. private $file;
  30. private $maxX;
  31. private $maxY;
  32. private $scalingUp;
  33. private $mimeType;
  34. private $keepAspect = false;
  35. //filemapper used for deleting previews
  36. // index is path, value is fileinfo
  37. static public $deleteFileMapper = array();
  38. static public $deleteChildrenMapper = array();
  39. /**
  40. * preview images object
  41. *
  42. * @var \OCP\IImage
  43. */
  44. private $preview;
  45. /**
  46. * @var \OCP\Files\FileInfo
  47. */
  48. protected $info;
  49. /**
  50. * check if thumbnail or bigger version of thumbnail of file is cached
  51. * @param string $user userid - if no user is given, OC_User::getUser will be used
  52. * @param string $root path of root
  53. * @param string $file The path to the file where you want a thumbnail from
  54. * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image
  55. * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image
  56. * @param bool $scalingUp Disable/Enable upscaling of previews
  57. * @throws \Exception
  58. * @return mixed (bool / string)
  59. * false if thumbnail does not exist
  60. * path to thumbnail if thumbnail exists
  61. */
  62. public function __construct($user = '', $root = '/', $file = '', $maxX = 1, $maxY = 1, $scalingUp = true) {
  63. //init fileviews
  64. if ($user === '') {
  65. $user = \OC_User::getUser();
  66. }
  67. $this->fileView = new \OC\Files\View('/' . $user . '/' . $root);
  68. $this->userView = new \OC\Files\View('/' . $user);
  69. //set config
  70. $this->configMaxX = \OC_Config::getValue('preview_max_x', null);
  71. $this->configMaxY = \OC_Config::getValue('preview_max_y', null);
  72. $this->maxScaleFactor = \OC_Config::getValue('preview_max_scale_factor', 2);
  73. //save parameters
  74. $this->setFile($file);
  75. $this->setMaxX($maxX);
  76. $this->setMaxY($maxY);
  77. $this->setScalingUp($scalingUp);
  78. $this->preview = null;
  79. //check if there are preview backends
  80. if (!\OC::$server->getPreviewManager()->hasProviders() && \OC::$server->getConfig()->getSystemValue('enable_previews', true)) {
  81. \OC_Log::write('core', 'No preview providers exist', \OC_Log::ERROR);
  82. throw new \Exception('No preview providers');
  83. }
  84. }
  85. /**
  86. * returns the path of the file you want a thumbnail from
  87. * @return string
  88. */
  89. public function getFile() {
  90. return $this->file;
  91. }
  92. /**
  93. * returns the max width of the preview
  94. * @return integer
  95. */
  96. public function getMaxX() {
  97. return $this->maxX;
  98. }
  99. /**
  100. * returns the max height of the preview
  101. * @return integer
  102. */
  103. public function getMaxY() {
  104. return $this->maxY;
  105. }
  106. /**
  107. * returns whether or not scalingup is enabled
  108. * @return bool
  109. */
  110. public function getScalingUp() {
  111. return $this->scalingUp;
  112. }
  113. /**
  114. * returns the name of the thumbnailfolder
  115. * @return string
  116. */
  117. public function getThumbnailsFolder() {
  118. return self::THUMBNAILS_FOLDER;
  119. }
  120. /**
  121. * returns the max scale factor
  122. * @return string
  123. */
  124. public function getMaxScaleFactor() {
  125. return $this->maxScaleFactor;
  126. }
  127. /**
  128. * returns the max width set in ownCloud's config
  129. * @return string
  130. */
  131. public function getConfigMaxX() {
  132. return $this->configMaxX;
  133. }
  134. /**
  135. * returns the max height set in ownCloud's config
  136. * @return string
  137. */
  138. public function getConfigMaxY() {
  139. return $this->configMaxY;
  140. }
  141. /**
  142. * @return false|Files\FileInfo|\OCP\Files\FileInfo
  143. */
  144. protected function getFileInfo() {
  145. $absPath = $this->fileView->getAbsolutePath($this->file);
  146. $absPath = Files\Filesystem::normalizePath($absPath);
  147. if(array_key_exists($absPath, self::$deleteFileMapper)) {
  148. $this->info = self::$deleteFileMapper[$absPath];
  149. } else if (!$this->info) {
  150. $this->info = $this->fileView->getFileInfo($this->file);
  151. }
  152. return $this->info;
  153. }
  154. /**
  155. * @return array|null
  156. */
  157. private function getChildren() {
  158. $absPath = $this->fileView->getAbsolutePath($this->file);
  159. $absPath = Files\Filesystem::normalizePath($absPath);
  160. if (array_key_exists($absPath, self::$deleteChildrenMapper)) {
  161. return self::$deleteChildrenMapper[$absPath];
  162. }
  163. return null;
  164. }
  165. /**
  166. * set the path of the file you want a thumbnail from
  167. * @param string $file
  168. * @return $this
  169. */
  170. public function setFile($file) {
  171. $this->file = $file;
  172. $this->info = null;
  173. if ($file !== '') {
  174. $this->getFileInfo();
  175. if($this->info instanceof \OCP\Files\FileInfo) {
  176. $this->mimeType = $this->info->getMimetype();
  177. }
  178. }
  179. return $this;
  180. }
  181. /**
  182. * set mime type explicitly
  183. * @param string $mimeType
  184. */
  185. public function setMimetype($mimeType) {
  186. $this->mimeType = $mimeType;
  187. }
  188. /**
  189. * set the the max width of the preview
  190. * @param int $maxX
  191. * @throws \Exception
  192. * @return \OC\Preview $this
  193. */
  194. public function setMaxX($maxX = 1) {
  195. if ($maxX <= 0) {
  196. throw new \Exception('Cannot set width of 0 or smaller!');
  197. }
  198. $configMaxX = $this->getConfigMaxX();
  199. if (!is_null($configMaxX)) {
  200. if ($maxX > $configMaxX) {
  201. \OC_Log::write('core', 'maxX reduced from ' . $maxX . ' to ' . $configMaxX, \OC_Log::DEBUG);
  202. $maxX = $configMaxX;
  203. }
  204. }
  205. $this->maxX = $maxX;
  206. return $this;
  207. }
  208. /**
  209. * set the the max height of the preview
  210. * @param int $maxY
  211. * @throws \Exception
  212. * @return \OC\Preview $this
  213. */
  214. public function setMaxY($maxY = 1) {
  215. if ($maxY <= 0) {
  216. throw new \Exception('Cannot set height of 0 or smaller!');
  217. }
  218. $configMaxY = $this->getConfigMaxY();
  219. if (!is_null($configMaxY)) {
  220. if ($maxY > $configMaxY) {
  221. \OC_Log::write('core', 'maxX reduced from ' . $maxY . ' to ' . $configMaxY, \OC_Log::DEBUG);
  222. $maxY = $configMaxY;
  223. }
  224. }
  225. $this->maxY = $maxY;
  226. return $this;
  227. }
  228. /**
  229. * set whether or not scalingup is enabled
  230. * @param bool $scalingUp
  231. * @return \OC\Preview $this
  232. */
  233. public function setScalingup($scalingUp) {
  234. if ($this->getMaxScaleFactor() === 1) {
  235. $scalingUp = false;
  236. }
  237. $this->scalingUp = $scalingUp;
  238. return $this;
  239. }
  240. /**
  241. * @param bool $keepAspect
  242. * @return $this
  243. */
  244. public function setKeepAspect($keepAspect) {
  245. $this->keepAspect = $keepAspect;
  246. return $this;
  247. }
  248. /**
  249. * check if all parameters are valid
  250. * @return bool
  251. */
  252. public function isFileValid() {
  253. $file = $this->getFile();
  254. if ($file === '') {
  255. \OC_Log::write('core', 'No filename passed', \OC_Log::DEBUG);
  256. return false;
  257. }
  258. if (!$this->fileView->file_exists($file)) {
  259. \OC_Log::write('core', 'File:"' . $file . '" not found', \OC_Log::DEBUG);
  260. return false;
  261. }
  262. return true;
  263. }
  264. /**
  265. * deletes previews of a file with specific x and y
  266. * @return bool
  267. */
  268. public function deletePreview() {
  269. $file = $this->getFile();
  270. $fileInfo = $this->getFileInfo($file);
  271. if($fileInfo !== null && $fileInfo !== false) {
  272. $fileId = $fileInfo->getId();
  273. $previewPath = $this->buildCachePath($fileId);
  274. return $this->userView->unlink($previewPath);
  275. }
  276. return false;
  277. }
  278. /**
  279. * deletes all previews of a file
  280. */
  281. public function deleteAllPreviews() {
  282. $toDelete = $this->getChildren();
  283. $toDelete[] = $this->getFileInfo();
  284. foreach ($toDelete as $delete) {
  285. if ($delete instanceof FileInfo) {
  286. /** @var \OCP\Files\FileInfo $delete */
  287. $fileId = $delete->getId();
  288. // getId() might return null, e.g. when the file is a
  289. // .ocTransferId*.part file from chunked file upload.
  290. if (!empty($fileId)) {
  291. $previewPath = $this->getPreviewPath($fileId);
  292. $this->userView->deleteAll($previewPath);
  293. $this->userView->rmdir($previewPath);
  294. }
  295. }
  296. }
  297. }
  298. /**
  299. * check if thumbnail or bigger version of thumbnail of file is cached
  300. * @param int $fileId fileId of the original image
  301. * @return string|false path to thumbnail if it exists or false
  302. */
  303. public function isCached($fileId) {
  304. if (is_null($fileId)) {
  305. return false;
  306. }
  307. $preview = $this->buildCachePath($fileId);
  308. //does a preview with the wanted height and width already exist?
  309. if ($this->userView->file_exists($preview)) {
  310. return $preview;
  311. }
  312. return $this->isCachedBigger($fileId);
  313. }
  314. /**
  315. * check if a bigger version of thumbnail of file is cached
  316. * @param int $fileId fileId of the original image
  317. * @return string|false path to bigger thumbnail if it exists or false
  318. */
  319. private function isCachedBigger($fileId) {
  320. if (is_null($fileId)) {
  321. return false;
  322. }
  323. // in order to not loose quality we better generate aspect preserving previews from the original file
  324. if ($this->keepAspect) {
  325. return false;
  326. }
  327. $maxX = $this->getMaxX();
  328. //array for usable cached thumbnails
  329. $possibleThumbnails = $this->getPossibleThumbnails($fileId);
  330. foreach ($possibleThumbnails as $width => $path) {
  331. if ($width < $maxX) {
  332. continue;
  333. } else {
  334. return $path;
  335. }
  336. }
  337. return false;
  338. }
  339. /**
  340. * get possible bigger thumbnails of the given image
  341. * @param int $fileId fileId of the original image
  342. * @return array an array of paths to bigger thumbnails
  343. */
  344. private function getPossibleThumbnails($fileId) {
  345. if (is_null($fileId)) {
  346. return array();
  347. }
  348. $previewPath = $this->getPreviewPath($fileId);
  349. $wantedAspectRatio = (float) ($this->getMaxX() / $this->getMaxY());
  350. //array for usable cached thumbnails
  351. $possibleThumbnails = array();
  352. $allThumbnails = $this->userView->getDirectoryContent($previewPath);
  353. foreach ($allThumbnails as $thumbnail) {
  354. $name = rtrim($thumbnail['name'], '.png');
  355. list($x, $y, $aspectRatio) = $this->getDimensionsFromFilename($name);
  356. if (abs($aspectRatio - $wantedAspectRatio) >= 0.000001
  357. || $this->unscalable($x, $y)
  358. ) {
  359. continue;
  360. }
  361. $possibleThumbnails[$x] = $thumbnail['path'];
  362. }
  363. ksort($possibleThumbnails);
  364. return $possibleThumbnails;
  365. }
  366. /**
  367. * @param string $name
  368. * @return array
  369. */
  370. private function getDimensionsFromFilename($name) {
  371. $size = explode('-', $name);
  372. $x = (int) $size[0];
  373. $y = (int) $size[1];
  374. $aspectRatio = (float) ($x / $y);
  375. return array($x, $y, $aspectRatio);
  376. }
  377. /**
  378. * @param int $x
  379. * @param int $y
  380. * @return bool
  381. */
  382. private function unscalable($x, $y) {
  383. $maxX = $this->getMaxX();
  384. $maxY = $this->getMaxY();
  385. $scalingUp = $this->getScalingUp();
  386. $maxScaleFactor = $this->getMaxScaleFactor();
  387. if ($x < $maxX || $y < $maxY) {
  388. if ($scalingUp) {
  389. $scalefactor = $maxX / $x;
  390. if ($scalefactor > $maxScaleFactor) {
  391. return true;
  392. }
  393. } else {
  394. return true;
  395. }
  396. }
  397. return false;
  398. }
  399. /**
  400. * return a preview of a file
  401. * @return \OCP\IImage
  402. */
  403. public function getPreview() {
  404. if (!is_null($this->preview) && $this->preview->valid()) {
  405. return $this->preview;
  406. }
  407. $this->preview = null;
  408. $file = $this->getFile();
  409. $maxX = $this->getMaxX();
  410. $maxY = $this->getMaxY();
  411. $scalingUp = $this->getScalingUp();
  412. $fileInfo = $this->getFileInfo($file);
  413. if($fileInfo === null || $fileInfo === false) {
  414. return new \OC_Image();
  415. }
  416. $fileId = $fileInfo->getId();
  417. $cached = $this->isCached($fileId);
  418. if ($cached) {
  419. $stream = $this->userView->fopen($cached, 'r');
  420. $this->preview = null;
  421. if ($stream) {
  422. $image = new \OC_Image();
  423. $image->loadFromFileHandle($stream);
  424. $this->preview = $image->valid() ? $image : null;
  425. $this->resizeAndCrop();
  426. fclose($stream);
  427. }
  428. }
  429. if (is_null($this->preview)) {
  430. $preview = null;
  431. $previewProviders = \OC::$server->getPreviewManager()->getProviders();
  432. foreach ($previewProviders as $supportedMimeType => $providers) {
  433. if (!preg_match($supportedMimeType, $this->mimeType)) {
  434. continue;
  435. }
  436. foreach ($providers as $closure) {
  437. $provider = $closure();
  438. if (!($provider instanceof \OCP\Preview\IProvider)) {
  439. continue;
  440. }
  441. \OC_Log::write('core', 'Generating preview for "' . $file . '" with "' . get_class($provider) . '"', \OC_Log::DEBUG);
  442. /** @var $provider Provider */
  443. $preview = $provider->getThumbnail($file, $maxX, $maxY, $scalingUp, $this->fileView);
  444. if (!($preview instanceof \OCP\IImage)) {
  445. continue;
  446. }
  447. $this->preview = $preview;
  448. $this->resizeAndCrop();
  449. $previewPath = $this->getPreviewPath($fileId);
  450. $cachePath = $this->buildCachePath($fileId);
  451. if ($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) {
  452. $this->userView->mkdir($this->getThumbnailsFolder() . '/');
  453. }
  454. if ($this->userView->is_dir($previewPath) === false) {
  455. $this->userView->mkdir($previewPath);
  456. }
  457. $this->userView->file_put_contents($cachePath, $preview->data());
  458. break 2;
  459. }
  460. }
  461. }
  462. if (is_null($this->preview)) {
  463. $this->preview = new \OC_Image();
  464. }
  465. return $this->preview;
  466. }
  467. /**
  468. * @param null|string $mimeType
  469. * @throws NotFoundException
  470. */
  471. public function showPreview($mimeType = null) {
  472. // Check if file is valid
  473. if($this->isFileValid() === false) {
  474. throw new NotFoundException('File not found.');
  475. }
  476. \OCP\Response::enableCaching(3600 * 24); // 24 hours
  477. if (is_null($this->preview)) {
  478. $this->getPreview();
  479. }
  480. if ($this->preview instanceof \OCP\IImage) {
  481. $this->preview->show($mimeType);
  482. }
  483. }
  484. /**
  485. * resize, crop and fix orientation
  486. * @return void
  487. */
  488. private function resizeAndCrop() {
  489. $image = $this->preview;
  490. $x = $this->getMaxX();
  491. $y = $this->getMaxY();
  492. $scalingUp = $this->getScalingUp();
  493. $maxScaleFactor = $this->getMaxScaleFactor();
  494. if (!($image instanceof \OCP\IImage)) {
  495. \OC_Log::write('core', '$this->preview is not an instance of \OCP\IImage', \OC_Log::DEBUG);
  496. return;
  497. }
  498. $realX = (int)$image->width();
  499. $realY = (int)$image->height();
  500. // compute $maxY and $maxX using the aspect of the generated preview
  501. if ($this->keepAspect) {
  502. $ratio = $realX / $realY;
  503. if($x / $ratio < $y) {
  504. // width restricted
  505. $y = $x / $ratio;
  506. } else {
  507. $x = $y * $ratio;
  508. }
  509. }
  510. if ($x === $realX && $y === $realY) {
  511. $this->preview = $image;
  512. return;
  513. }
  514. $factorX = $x / $realX;
  515. $factorY = $y / $realY;
  516. if ($factorX >= $factorY) {
  517. $factor = $factorX;
  518. } else {
  519. $factor = $factorY;
  520. }
  521. if ($scalingUp === false) {
  522. if ($factor > 1) {
  523. $factor = 1;
  524. }
  525. }
  526. if (!is_null($maxScaleFactor)) {
  527. if ($factor > $maxScaleFactor) {
  528. \OC_Log::write('core', 'scale factor reduced from ' . $factor . ' to ' . $maxScaleFactor, \OC_Log::DEBUG);
  529. $factor = $maxScaleFactor;
  530. }
  531. }
  532. $newXSize = (int)($realX * $factor);
  533. $newYSize = (int)($realY * $factor);
  534. $image->preciseResize($newXSize, $newYSize);
  535. if ($newXSize === $x && $newYSize === $y) {
  536. $this->preview = $image;
  537. return;
  538. }
  539. if ($newXSize >= $x && $newYSize >= $y) {
  540. $cropX = floor(abs($x - $newXSize) * 0.5);
  541. //don't crop previews on the Y axis, this sucks if it's a document.
  542. //$cropY = floor(abs($y - $newYsize) * 0.5);
  543. $cropY = 0;
  544. $image->crop($cropX, $cropY, $x, $y);
  545. $this->preview = $image;
  546. return;
  547. }
  548. if (($newXSize < $x || $newYSize < $y) && $scalingUp) {
  549. if ($newXSize > $x) {
  550. $cropX = floor(($newXSize - $x) * 0.5);
  551. $image->crop($cropX, 0, $x, $newYSize);
  552. }
  553. if ($newYSize > $y) {
  554. $cropY = floor(($newYSize - $y) * 0.5);
  555. $image->crop(0, $cropY, $newXSize, $y);
  556. }
  557. $newXSize = (int)$image->width();
  558. $newYSize = (int)$image->height();
  559. //create transparent background layer
  560. $backgroundLayer = imagecreatetruecolor($x, $y);
  561. $white = imagecolorallocate($backgroundLayer, 255, 255, 255);
  562. imagefill($backgroundLayer, 0, 0, $white);
  563. $image = $image->resource();
  564. $mergeX = floor(abs($x - $newXSize) * 0.5);
  565. $mergeY = floor(abs($y - $newYSize) * 0.5);
  566. imagecopy($backgroundLayer, $image, $mergeX, $mergeY, 0, 0, $newXSize, $newYSize);
  567. //$black = imagecolorallocate(0,0,0);
  568. //imagecolortransparent($transparentlayer, $black);
  569. $image = new \OC_Image($backgroundLayer);
  570. $this->preview = $image;
  571. return;
  572. }
  573. }
  574. /**
  575. * @param array $args
  576. */
  577. public static function post_write($args) {
  578. self::post_delete($args, 'files/');
  579. }
  580. /**
  581. * @param array $args
  582. */
  583. public static function prepare_delete_files($args) {
  584. self::prepare_delete($args, 'files/');
  585. }
  586. /**
  587. * @param array $args
  588. * @param string $prefix
  589. */
  590. public static function prepare_delete($args, $prefix='') {
  591. $path = $args['path'];
  592. if (substr($path, 0, 1) === '/') {
  593. $path = substr($path, 1);
  594. }
  595. $view = new \OC\Files\View('/' . \OC_User::getUser() . '/' . $prefix);
  596. $absPath = Files\Filesystem::normalizePath($view->getAbsolutePath($path));
  597. self::addPathToDeleteFileMapper($absPath, $view->getFileInfo($path));
  598. if ($view->is_dir($path)) {
  599. $children = self::getAllChildren($view, $path);
  600. self::$deleteChildrenMapper[$absPath] = $children;
  601. }
  602. }
  603. /**
  604. * @param string $absolutePath
  605. * @param \OCP\Files\FileInfo $info
  606. */
  607. private static function addPathToDeleteFileMapper($absolutePath, $info) {
  608. self::$deleteFileMapper[$absolutePath] = $info;
  609. }
  610. /**
  611. * @param \OC\Files\View $view
  612. * @param string $path
  613. * @return array
  614. */
  615. private static function getAllChildren($view, $path) {
  616. $children = $view->getDirectoryContent($path);
  617. $childrensFiles = array();
  618. $fakeRootLength = strlen($view->getRoot());
  619. for ($i = 0; $i < count($children); $i++) {
  620. $child = $children[$i];
  621. $childsPath = substr($child->getPath(), $fakeRootLength);
  622. if ($view->is_dir($childsPath)) {
  623. $children = array_merge(
  624. $children,
  625. $view->getDirectoryContent($childsPath)
  626. );
  627. } else {
  628. $childrensFiles[] = $child;
  629. }
  630. }
  631. return $childrensFiles;
  632. }
  633. /**
  634. * @param array $args
  635. */
  636. public static function post_delete_files($args) {
  637. self::post_delete($args, 'files/');
  638. }
  639. /**
  640. * @param array $args
  641. * @param string $prefix
  642. */
  643. public static function post_delete($args, $prefix='') {
  644. $path = Files\Filesystem::normalizePath($args['path']);
  645. $preview = new Preview(\OC_User::getUser(), $prefix, $path);
  646. $preview->deleteAllPreviews();
  647. }
  648. /**
  649. * @param int $fileId
  650. * @return string
  651. */
  652. private function buildCachePath($fileId) {
  653. $maxX = $this->getMaxX();
  654. $maxY = $this->getMaxY();
  655. $previewPath = $this->getPreviewPath($fileId);
  656. $preview = $previewPath . strval($maxX) . '-' . strval($maxY);
  657. if ($this->keepAspect) {
  658. $preview .= '-with-aspect';
  659. }
  660. $preview .= '.png';
  661. return $preview;
  662. }
  663. /**
  664. * @param int $fileId
  665. * @return string
  666. */
  667. private function getPreviewPath($fileId) {
  668. return $this->getThumbnailsFolder() . '/' . $fileId . '/';
  669. }
  670. }