Support thumbnailing non-image files and straighten out setup for 'gd'

Summary:
Make 'gd' an explicit optional dependency, test for it in setup, and make the
software behave correctly if it is not available.

When generating file thumnails, provide reasonable defaults and behavior for
non-image files.

Test Plan:
Uploaded text files, pdf files, etc., and got real thumbnails instead of a
broken image.

Simulated setup and gd failures and walked through setup process and image
fallback for thumbnails.

Reviewed By: aran
Reviewers: toulouse, jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 446
This commit is contained in:
epriestley
2011-06-13 08:43:42 -07:00
parent cb0cbc50ad
commit f706093933
11 changed files with 117 additions and 9 deletions

View File

@@ -43,12 +43,10 @@ class PhabricatorFileTransformController extends PhabricatorFileController {
return new Aphront404Response();
}
if (!$file->isViewableInBrowser()) {
return new Aphront400Response();
}
$type = $file->getMimeType();
if (!$file->isTransformableImage()) {
return new Aphront400Response();
if (!$file->isViewableInBrowser() || !$file->isTransformableImage()) {
return $this->buildDefaultTransformation($file);
}
switch ($this->transform) {
@@ -78,6 +76,39 @@ class PhabricatorFileTransformController extends PhabricatorFileController {
return $this->buildTransformedFileResponse($xform);
}
private function buildDefaultTransformation(PhabricatorFile $file) {
static $regexps = array(
'@application/zip@' => 'zip',
'@image/@' => 'image',
'@application/pdf@' => 'pdf',
'@.*@' => 'default',
);
$type = $file->getMimeType();
$prefix = 'default';
foreach ($regexps as $regexp => $implied_prefix) {
if (preg_match($regexp, $type)) {
$prefix = $implied_prefix;
break;
}
}
switch ($this->transform) {
case 'thumb-160x120':
$suffix = '160x120';
break;
case 'thumb-60x45':
$suffix = '60x45';
break;
default:
throw new Exception("Unsupported transformation type!");
}
$path = "/rsrc/image/icon/fatcow/thumbnails/{$prefix}{$suffix}.png";
return id(new AphrontRedirectResponse())
->setURI($path);
}
private function buildTransformedFileResponse(
PhabricatorTransformedFile $xform) {
@@ -123,9 +154,25 @@ class PhabricatorFileTransformController extends PhabricatorFileController {
$dx, $dy,
$scale * $dx, $scale * $dy);
ob_start();
imagejpeg($dst);
return ob_get_clean();
$img = null;
if (function_exists('imagejpeg')) {
ob_start();
imagejpeg($dst);
$img = ob_get_clean();
} else if (function_exists('imagepng')) {
ob_start();
imagepng($dst);
$img = ob_get_clean();
} else if (function_exists('imagegif')) {
ob_start();
imagegif($dst);
$img = ob_get_clean();
} else {
throw new Exception("No image generation functions exist!");
}
return $img;
}
}

View File

@@ -216,7 +216,35 @@ class PhabricatorFile extends PhabricatorFileDAO {
}
public function isTransformableImage() {
return preg_match('@^image/(gif|png|jpe?g)@', $this->getViewableMimeType());
// NOTE: The way the 'gd' extension works in PHP is that you can install it
// with support for only some file types, so it might be able to handle
// PNG but not JPEG. Try to generate thumbnails for whatever we can. Setup
// warns you if you don't have complete support.
$matches = null;
$ok = preg_match(
'@^image/(gif|png|jpe?g)@',
$this->getViewableMimeType(),
$matches);
if (!$ok) {
return false;
}
switch ($matches[1]) {
case 'jpg';
case 'jpeg':
return function_exists('imagejpeg');
break;
case 'png':
return function_exists('imagepng');
break;
case 'gif':
return function_exists('imagegif');
break;
default:
throw new Exception('Unknown type matched as image MIME type.');
}
}
public function getViewableMimeType() {