我试图实现的是创建一个到存储文件夹的路由,这样即使它不在public
目录下,我也可以访问它。
例如,用户的头像位于app'storage'user'avatars'avatar.jpg
中,我想制定一条路线,这样我就可以从类似http://localhost/user/avatars/avatar.jpg
的地方访问这些图像。
我怎样才能做到这一点?
做这件事的最好方法是使用Response::download()
来提供公用文件夹之外的文件:
创建路由器:
Route::get('/user/avatars/{avatarName}', 'AvatarServerController@downloadAvatar');
在这可能是控制器控制器你做
class AvatarServerController extends Controller {
public function downloadAvatar($avatarName)
{
$fileName = storage_path()."/user/avatars/$avatarName";
if (File::exists($fileName))
{
return Response::download(fileName);
}
return Redirect::route('home')->withMessage('Avatar file not found.');
}
}
但是,仍然允许访问公共文件夹以外的任何内容可能会带来严重的安全风险,这就是为什么Laravel是这样构建的。但还有一些其他选择:
1) 创建符号链接:
ln -s /var/www/site/app/storage/user/avatars /var/www/site/public/user/avatars
然后直接使用它们:
HTML::image('user/avatar/avatar.jpg', 'User avatar');
3) 创建一个指向app/storage/user/avatars
目录的虚拟主机别名。
首先,我建议将avatars文件夹移到更公开的地方。但作为拉拉威尔,你可以实现任何你想要的。
Route::get('user/avatars/{filename}', function($filename)
{
$filePath = storage_path().'/user/avatars/'.$filename;
if ( ! File::exists($filePath) or ( ! $mimeType = getImageContentType($filePath)))
{
return Response::make("File does not exist.", 404);
}
$fileContents = File::get($filePath);
return Response::make($fileContents, 200, array('Content-Type' => $mimeType));
});
然后在某个地方添加这个自定义助手功能:
function getImageContentType($file)
{
$mime = exif_imagetype($file);
if ($mime === IMAGETYPE_JPEG)
$contentType = 'image/jpeg';
elseif ($mime === IMAGETYPE_GIF)
$contentType = 'image/gif';
else if ($mime === IMAGETYPE_PNG)
$contentType = 'image/png';
else
$contentType = false;
return $contentType;
}
值得注意的是,您提出的方法和解决方案存在安全问题。
实现这一点的更好方法是在web服务器上使用别名或重写。
如果您正在使用nginx,请将其添加到您的服务器块:
# Rewrite for user avatars
location /user/ {
root /var/www/laravel/app/storage/user;
}
对于Apache,请使用"Alias"
Alias /user /var/www/laravel/app/storage/user
这样做比为每个图像请求引导Laravel更快、性能更好。