Задать вопрос
dima9595
@dima9595
Junior PHP

Как разделить видеофайл на небольшие фрагменты и загрузить на сервер?

Пешу пет-проект для саморазвития и столкнулся со следующей проблемой:
На сайте есть форма загрузки файлов. Все файлы разделяются на чанки и по очереди загружаются на сервер по api.
На первом чанке создаётся файл, а на последующих дополняется текст (из чанка) в конце файла.

Загружать фото/pdf в таком формате получается. А вот с архивами и видео (только эти форматы ещё проверил) не подходит. Архив вообще не открывается (даже ошибки нет), а видео максимум длится пару секунд (скорей всего это нормальный первый чанк созданный) и зависает.

PS: В идеале хочу в S3 хранилище загрузить. Но пока тестирую - загружаю локально.

Обработка чанков и их загрузка:
const uploadFile = async () => {
	let number_chunk = 1;
	let max_chunk = chunks.value.length;

	statusUpload.value = true;

	for (let chunk of chunks.value) {
		const upload = await uploadChunk(chunk, number_chunk, max_chunk);

		if (!upload) {
			console.log('Ошибка загрузки файла')
			break;
		}

		activeUploadChunk.value += 1;
		number_chunk += 1;
	}

	statusUpload.value = false;
}


Загрузка файла:
const uploadChunk = async (chunk, number_chunk, max_chunk) => {
	let formData = new FormData();
	formData.append('name', file.value.files[0].name)
	formData.append('type', file.value.files[0].type)
	formData.append('number_chunk', number_chunk)
	formData.append('max_chunk', max_chunk)
	formData.append('chunk', chunk);

	const {data, error} = await useAsyncData(() => client('/api/videos/upload', {
		method: 'post',
		body: formData,
	}));

	return error;
}


Laravel метод загрузки:
public function upload(Request $request)
    {
        if ($request->hasFile('chunk')) {
            $data = $request->all();
            $chunk = $request->file('chunk');

            // Имя файла
            $fileName = $data['name'];
            $exlodeName = explode('.', $fileName);
            $fileExtension = $exlodeName[count($exlodeName) - 1];
            $fileName = md5($fileName) . '.' . $fileExtension;

            $storage = Storage::disk('public');

            try {
                if ($data['number_chunk'] === 1) {
                    $save = $storage->put($fileName, new File($chunk));
                } else {
                    $save = $storage->append($fileName, file_get_contents($chunk));
                }

                sleep(1);

                if ($save) {
                    return response()->json([
                        'type' => 'success',
                        'message' => 'Файл успешно загружен',
                    ], 200);
                }
            } catch (Exception $e) {
                return response()->json([
                    'type' => 'error',
                    'message' => 'Ошибка загрузки файла',
                ], 500);
            }
        }
    }


Вообще правильно ли я делаю или есть более удобный и правильный вариант (без плагинов/компонентов и т.п.)? Заранее спасибо.
  • Вопрос задан
  • 270 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
dima9595
@dima9595 Автор вопроса
Junior PHP
Решено. Спасибо за наводку YepBro на счёт сверки файлов побайтово. Это дало понять что не правильно записывал файл.
Решение:
$save = $storage->append($fileNameBlob, file_get_contents($chunk));

поменять на
$save = file_put_contents(storage_path('/app/public/' . $fileNameBlob), file_get_contents($chunk), FILE_APPEND | LOCK_EX);

Флаг "LOCK_EX", наверное, необязателен. Но ради блокировки записи я его поставил.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы