Открытие тяжелых видео в браузере
Добавлено: 2023.06.01, 10:29
Всех приветствую.
Имеется микросервис, в котором хранятся различные pdf и mp4 файлы. Есть такой метод API в контроллере, для отдачи файла во внешний мир:
С не очень большими файлами сложностей нет, они получаются и выводятся в браузер. Проблема возникает для больших видео файлов (например, 1.9 Гб). Пробую вот так:
При открытии ссылки файл начинает загружаться, во вкладке появляется видеоплеер, но затем происходит ошибка 500 Internal Server Error.
В логах такое:
Насколько я понимаю, нужно каким-то образом отправить в браузер файл по частям, потому-что file_get_contents() получает файл целиком в строку.
И проблем бы не было, если бы файл хранился там же, где мы его хотим открыть. Проводил эксперимент: нужный файл скопировал в папку web того приложения, где его требуется получить и вывел в браузер следующим образом:
Но с учетом того, что файл лежит на другом хосте, я пока так и не понял, какие правки нужно внести. Нужно ли править метод API? Какие правки нужны на клиенте?
Буду рад любой вашей помощи.
Имеется микросервис, в котором хранятся различные pdf и mp4 файлы. Есть такой метод API в контроллере, для отдачи файла во внешний мир:
Код: Выделить всё
// API контроллер
/**
* Получение файла.
* @param int $id
* @return \yii\web\Response
* @throws NotFoundHttpException
*/
public function actionGetFile($id)
{
/* @var $model \app\models\File */
$model = $this->findModel($id);
$filepath = Yii::getAlias("@files/$model->id/$model->filename");
if (!is_file($filepath)) {
throw new NotFoundHttpException("Файл с идентификатором $id не найден.");
}
return $this->response->sendFile($filepath);
}
Код: Выделить всё
// контроллер на стороне клиента, обращающегося к сервису за файлом
/**
* Getting file.
* @param int $id
* @return \yii\web\Response
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionGetFile($id)
{
$model = $this->findModel($id);
$url = "https://hostname.ru/api/file/$file_id/get-file?access-token=token";
try {
$file = file_get_contents($url);
} catch(\yii\base\ErrorException $e) {
throw new \yii\web\NotFoundHttpException('Файл не найден.');
}
if ($model->type === File::TYPE_VIDEO) {
$mimeType = 'video/mp4';
} else {
$mimeType = 'application/pdf';
}
// FIXME: not working with large video files
return $this->response->sendContentAsFile(
$file,
"Файл $file_id",
['mimeType' => $mimeType, 'inline' => true]
);
}
В логах такое:
Код: Выделить всё
[error][yii\base\ErrorException:1] yii\base\ErrorException: Allowed memory size of 3145728000 bytes exhausted (tried to allocate 1939918848 bytes) in /home/roman/eclipse-workspace/employee/vendor/yiisoft/yii2/web/Response.php:433
И проблем бы не было, если бы файл хранился там же, где мы его хотим открыть. Проводил эксперимент: нужный файл скопировал в папку web того приложения, где его требуется получить и вывел в браузер следующим образом:
Код: Выделить всё
/**
* Getting file.
* @param int $id
* @return \yii\web\Response
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionGetFile($id)
{
$url = 'file.mp4';
$handle = fopen($url, 'rb');
// work for LOCAL large file
return Yii::$app->response->sendStreamAsFile(
$handle,
"Файл $file_id",
['mimeType' => 'video/mp4', 'inline' => true]
);
}
Буду рад любой вашей помощи.