【问题标题】:Laravel 5.6 download file ajaxLaravel 5.6 下载文件 ajax
【发布时间】:2018-06-13 15:10:18
【问题描述】:

我在 Laravel 5.6 中有一个 REST API

用户可以将他们的文件上传到非公共文件夹中。

我的问题是,现在我只想让用户下载文件,前提是 JWT 令牌有效并且用户具有正确的权限。

我的实际代码如下:

jquery:

$.ajaxSetup({
    headers: {
        'Authorization': 'Bearer ' + token
});

$.get('/api//download?' + $.param({
     file: encodeURIComponent(fileNonPublicPath) //e.g. company_id/file.pdf
}))
.done((data) => {
     console.log('file content', data);
})
.fail((err) => {
      console.error(err);
});

Laravel 控制器:

$file = urldecode($request->input('file'));
$user = JWTAuth::toUser($request->token);
if(checkUserRole($user,$file){
   $pathToFile = Storage::disk('documents')->getDriver()->getAdapter()->applyPathPrefix($file);
   $finfo = finfo_open(FILEINFO_MIME_TYPE);
   $mime = finfo_file($finfo, $pathToFile);
   finfo_close($finfo);
   $headers = array('Content-Type' => $mime,);
   return response()->download($pathToFile, 'originalfilename', $headers);
}
return response()->json([], 403); //forbidden

此代码工作正常,只是浏览器以 ajax 格式接收文件内容,然后用户无法下载。

有什么解决方案不影响存储文件的安全性?

【问题讨论】:

    标签: php jquery ajax laravel-5 download


    【解决方案1】:

    如果下载不是文件,则需要流式传输。 response->streamDownload()

    From the docs:

    有时您可能希望将给定操作的字符串响应转换为可下载响应,而无需将操作的内容写入磁盘。在这种情况下,您可以使用 streamDownload 方法。此方法接受回调、文件名和可选的标头数组作为其参数:

    return response()->streamDownload(function () {
    echo GitHub::api('repo')
                ->contents()
                ->readme('laravel', 'laravel')['contents'];
    }, 'laravel-readme.md');
    

    【讨论】:

    • 感谢您的回答。你能用我的代码举个例子吗?谢谢
    【解决方案2】:

    我使用以下解决方案解决了它:

    在 javascript 文件中:

    // onclick callback:
    window.location = '/download?' + $.param({
       token: encodeURIComponent(STRING_TOKEN),
       file: encodeURIComponent(file)
    });    
    

    在 web.php 中创建一个新的非保护路由

    Route::get('/download', 'UploadController@download');
    

    在 UploadController 中:

    $file = urldecode($request->input('file'));
    $token = urldecode($request->input('token'));
    
    //This doesn't work
    // $user = JWTAuth::toUser($token);
    
    // Then I used the same lib that JWTAuth uses to encode/decode the token
    $secret = config('jwt.secret');
    $jws = SimpleJWS::load($token);
    if (!$jws->isValid($secret)) {
        return response()->json([], 401); // unauthorized
    } 
    $payload = $jws->getPayload();
    $userId = User::find($payload["user"]["id"]);
    
    $user = App\User::find($userId);
    if(checkUserRole($user,$file){ 
       $pathToFile = Storage::disk('documents')->getDriver()->getAdapter()->applyPathPrefix($file);
       $finfo = finfo_open(FILEINFO_MIME_TYPE);
       $mime = finfo_file($finfo, $pathToFile);
       finfo_close($finfo);
       $headers = array('Content-Type' => $mime,);
       return response()->download($pathToFile, 'originalfilename', $headers);
     }
     return response()->json([], 403); //forbidden
    

    这应该足够安全。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-02
      • 1970-01-01
      • 2018-12-13
      • 1970-01-01
      • 2016-04-03
      • 2018-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多