Laravel 5.6下载文件ajax

时间:2018-06-13 15:10:18

标签: php jquery ajax laravel-5 download

我在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中接收文件的内容,然后用户无法下载。

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

2 个答案:

答案 0 :(得分:0)

如果文件不是,则需要对下载进行流式传输。 #!/bin/sh from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver import FirefoxOptions opts = FirefoxOptions() opts.add_argument("--headless") driver = webdriver.Firefox(firefox_options=opts) driver.get("https://www.exampledomain.com") username = driver.find_element_by_id("txtUser") password = driver.find_element_by_id("txtPass") username.send_keys("XXXXX") password.send_keys("XXXXX") driver.find_element_by_name("submit").click() driver.close()

From the docs

  

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

response->streamDownload()

答案 1 :(得分:0)

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

在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

这应该足够安全。