Ben Swinburne's answer 是绝对正确的 - 他应该得到积分!对我来说,尽管答案在 Laravel 5.1 中有点悬而未决,这让我进行了研究——而在 5.2(激发了这个答案)中,有一种新方法可以快速完成。
注意:此答案包含支持 UTF-8 文件名的提示,但建议考虑跨平台支持!
在 Laravel 5.2 中,您现在可以这样做:
$pathToFile = '/documents/filename.pdf'; // or txt etc.
// when the file name (display name) is decided by the name in storage,
// remember to make sure your server can store your file name characters in the first place (!)
// then encode to respect RFC 6266 on output through content-disposition
$fileNameFromStorage = rawurlencode(basename($pathToFile));
// otherwise, if the file in storage has a hashed file name (recommended)
// and the display name comes from your DB and will tend to be UTF-8
// encode to respect RFC 6266 on output through content-disposition
$fileNameFromDatabase = rawurlencode('пожалуйста.pdf');
// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
return response()->file(storage_path($pathToFile), [
'Content-Disposition' => str_replace('%name', $fileNameFromDatabase, "inline; filename=\"%name\"; filename*=utf-8''%name"),
'Content-Type' => Storage::getMimeType($pathToFile), // e.g. 'application/pdf', 'text/plain' etc.
]);
在 Laravel 5.1 中,您可以通过带有 a Response Macro in the boot method 的服务提供者添加上述方法 response()->file() 作为后备(如果您将其设为类,请确保使用其在 config/app.php 中的命名空间进行注册)。开机方法内容:
// Be aware that I excluded the Storage::exists() and / or try{}catch(){}
$factory->macro('file', function ($pathToFile, array $userHeaders = []) use ($factory) {
// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
$storagePath = str_ireplace('app/', '', $pathToFile); // 'app/' may change if different in your configuration
$fileContents = Storage::get($storagePath);
$fileMimeType = Storage::getMimeType($storagePath); // e.g. 'application/pdf', 'text/plain' etc.
$fileNameFromStorage = basename($pathToFile); // strips the path and returns filename with extension
$headers = array_merge([
'Content-Disposition' => str_replace('%name', $fileNameFromStorage, "inline; filename=\"%name\"; filename*=utf-8''%name"),
'Content-Length' => strlen($fileContents), // mb_strlen() in some cases?
'Content-Type' => $fileMimeType,
], $userHeaders);
return $factory->make($fileContents, 200, $headers);
});
你们中的一些人不喜欢 Laravel Facades 或 Helper 方法,但那是你的选择。如果 Ben Swinburne's answer 不适合你,这应该会给你一些指导。
意见提示:您不应该将文件存储在数据库中。尽管如此,此答案仅在您删除 Storage 外观部分时才有效,将内容而不是路径作为第一个参数作为@BenSwinburne 答案的第一个参数。