Laravel 5.6 скачать файл ajax

У меня есть REST API в Laravel 5.6

Пользователи могут загружать свой файл в непубличную папку.

Моя проблема в том, что теперь я хочу разрешить пользователю загружать файл только в том случае, если токен JWT действителен и если у пользователя есть необходимые права.

Мой фактический код следующий:

jquery:

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

$.get('/api//download?' + $.param({
     file: encodeURIComponent(fileNonPublicPath) //e.g. company_id/file.pdf
}))
.done((data) => {
     console.info('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 в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
4 189
2

Ответы 2

Вам необходимо выполнить потоковую загрузку, если это не файл. response->streamDownload()

Из документов:

Sometimes you may wish to turn the string response of a given operation into a downloadable response without having to write the contents of the operation to disk. You may use the streamDownload method in this scenario. This method accepts a callback, file name, and an optional array of headers as its arguments:

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

Спасибо за ваш ответ. Можете ли вы привести пример с моим кодом? Спасибо

Fabry 13.06.2018 17:27

Я решил это с помощью следующего решения:

в файле 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

Это должно быть достаточно безопасно.

Другие вопросы по теме