本文目录导读:

在 Laravel 中实现临时文件下载链接有多种方式,以下是几种常用的解决方案:
使用临时签名路由(推荐)
生成临时下载链接
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Storage;
// 在路由中定义下载路由
Route::get('/download/{file}', function ($file) {
// 验证文件存在
if (!Storage::disk('local')->exists($file)) {
abort(404);
}
// 获取文件信息
$filePath = Storage::disk('local')->path($file);
$fileName = basename($file);
// 返回下载响应
return response()->download($filePath, $fileName);
})->middleware('signed'); // 使用签名中间件
// 生成临时链接
$url = URL::temporarySignedRoute(
'download', // 路由名称
now()->addMinutes(30), // 30分钟后过期
['file' => '12345/report.pdf'] // 参数
);
使用控制器方法
// 控制器
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class FileDownloadController extends Controller
{
public function download(Request $request, $file)
{
// 验证签名
if (!$request->hasValidSignature()) {
abort(401);
}
// 验证文件存在
if (!Storage::disk('local')->exists($file)) {
abort(404);
}
// 文件下载
return Storage::disk('local')->download($file);
}
// 生成下载链接
public function generateLink(Request $request)
{
$file = '12345/report.pdf';
$expires = now()->addHours(2);
$url = URL::temporarySignedRoute(
'file.download',
$expires,
['file' => $file]
);
return response()->json([
'download_url' => $url,
'expires_at' => $expires->toDateTimeString()
]);
}
}
// 路由
Route::get('/files/download/{file}', [FileDownloadController::class, 'download'])
->name('file.download')
->middleware('signed');
使用缓存存储临时代理
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class FileProxyController extends Controller
{
public function createTemporaryLink(Request $request)
{
$file = $request->input('file');
$minutes = $request->input('expires', 30);
// 生成唯一token
$token = Str::random(40);
// 存储到缓存
Cache::put(
"file_token_{$token}",
['file' => $file],
now()->addMinutes($minutes)
);
return url("/temp-download/{$token}");
}
public function downloadFile($token)
{
// 从缓存获取文件信息
$data = Cache::get("file_token_{$token}");
if (!$data) {
abort(404, '链接已过期');
}
$file = $data['file'];
// 清理token(一次性使用)
Cache::forget("file_token_{$token}");
return response()->download(storage_path("app/{$file}"));
}
}
// 路由
Route::post('/create-temp-link', [FileProxyController::class, 'createTemporaryLink']);
Route::get('/temp-download/{token}', [FileProxyController::class, 'downloadFile']);
使用 Laravel 的临时URL方法
use Illuminate\Support\Facades\Storage;
// 获取 S3 临时URL
$url = Storage::disk('s3')->temporaryUrl(
'path/to/file.pdf', // 文件路径
now()->addMinutes(10), // 有效期
[
'ResponseContentType' => 'application/pdf',
'ResponseContentDisposition' => 'attachment; filename="file.pdf"',
]
);
综合示例:完整的下载链接控制器
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
class TemporaryDownloadController extends Controller
{
/**
* 生成临时下载链接
*/
public function generate(Request $request)
{
$request->validate([
'file' => 'required|string',
'expires' => 'nullable|integer|min:1|max:1440', // 分钟数
]);
$file = $request->file;
$expires = $request->expires ?? 30;
// 检查文件是否存在
if (!Storage::exists($file)) {
return response()->json(['error' => '文件不存在'], 404);
}
// 生成签名URL
$url = URL::temporarySignedRoute(
'download.temp',
now()->addMinutes($expires),
['file' => $file]
);
return response()->json([
'success' => true,
'url' => $url,
'expires_in' => $expires . ' minutes',
'expires_at' => now()->addMinutes($expires)->toDateTimeString()
]);
}
/**
* 处理下载请求
*/
public function download(Request $request)
{
// 验证签名
if (!$request->hasValidSignature()) {
abort(403, '下载链接无效或已过期');
}
$file = $request->file;
// 检查文件存在
if (!Storage::exists($file)) {
abort(404, '文件不存在');
}
// 生成文件名
$filename = basename($file);
// 返回下载
return Storage::download($file, $filename);
}
}
// 路由定义
Route::post('/generate-download-link', [TemporaryDownloadController::class, 'generate']);
Route::get('/download/temp/{file}', [TemporaryDownloadController::class, 'download'])
->name('download.temp')
->middleware('signed');
前端调用示例
<!-- 生成链接表单 -->
<form id="generateForm">
<input type="text" name="file" placeholder="文件路径" required>
<input type="number" name="expires" placeholder="有效期(分钟)" value="30" min="1" max="1440">
<button type="submit">生成下载链接</button>
</form>
<!-- JavaScript -->
<script>
document.getElementById('generateForm').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
try {
const response = await fetch('/generate-download-link', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Content-Type': 'application/json'
},
body: JSON.stringify({
file: formData.get('file'),
expires: parseInt(formData.get('expires'))
})
});
const data = await response.json();
if (data.success) {
console.log('下载链接:', data.url);
console.log('过期时间:', data.expires_at);
// 显示链接
document.getElementById('downloadLink').innerHTML =
`<a href="${data.url}" target="_blank">下载文件</a>`;
}
} catch (error) {
console.error('生成链接失败:', error);
}
});
</script>
安全建议
- 设置合理的过期时间:根据文件敏感度设置不同的有效期
- 限制下载次数:对于重要文件可以限制下载次数
- 记录下载日志:记录谁在何时下载了什么文件
- 文件权限控制:确保只有授权用户才能生成链接
选择哪种方案取决于你的具体需求:
- 签名路由:最安全,适合简单场景
- 缓存机制:可以控制下载次数,适合一次性下载
- S3临时URL:适合云存储,性能最好
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播