Задать вопрос
@vadik_nv

Как загружать большие файлы асинхронно с формы сайта на облачное хранилище s3?

Задача загружать большие видео размером примерно 2G на бакет yandex.cloud.
Проблема в долгой отправке формы/запроса.
Есть приложение на vue + laravel.
1) пробовал отправлять файл axios POST запрос -> laravel backend -> aws/s3 - запрос выполняется около 15 минут, после этого консольной командой файл заливается в облако.
2) безсерверная отправка сабмитом формы напрямую на облако - форма сабмитится те же 15 минут

В обоих случаях надо ждать 15 мин для того чтобы выполнился запрос, это не подходит. Пользователям нужно как можно скорее загружать следующее видео.
Примеры кода прикреплю если будет интересно. Тут больше важен выбор подхода. Подскажите пожалуйста как можно быстро отправлять форму/запрос чтобы загрузка шла в фоне и пользователи могли перезагружать страницу, загружать следующее видео. Желательно без сильной нагрузки на backend.
Допускаю что я многого не знаю или что-то упустил, к примеру на ютубе форма моментально отрабатывает, понятно что это другой уровень и другие технологии.
  • Вопрос задан
  • 99 просмотров
Подписаться 1 Простой 1 комментарий
Пригласить эксперта
Ответы на вопрос 4
ThunderCat
@ThunderCat
{PHP, MySql, HTML, JS, CSS} developer
Подскажите пожалуйста как можно быстро отправлять форму/запрос чтобы загрузка шла в фоне и пользователи могли перезагружать страницу, загружать следующее видео.
Короткий ответ - никак. Если пользователь будет перегружать страницу загрузка прервется. Это касается любого сервиса, будь то ютуб, вк или что-то другое.

Вероятно у вас неверно изложена задача, скорее всего пользователь должен иметь возможность взаимодействовать с сайтом, а не перегружать страницу.
Ответ написан
Комментировать
Sanes
@Sanes
Чтобы пользоваться сайтом и не прерывать загрузку, вы должны реализовать интерфейс с применением Ajax. Как только с этим разберетесь, все встанет на свои места. Примерно тоже самое, что разного рода онлайн-плееры.
Ответ написан
Комментировать
@weart
Можно юзать s3 js sdk с встроенным прогрессом загрузки (самый простой вариант)

Я использую s3 php sdk + xhr, чтобы отобразить прогресс, чтобы юзер видел, что ничего не повисло. Гиг около 2 минут заливается на моем инете
Ответ написан
Комментировать
@vadik_nv Автор вопроса
В общем решил проблему прямой отправкой на бакет, ещё сделал сеттер процентов прогрессбара через Vuex.
Код отправки файла на бакет.
let xhr = new XMLHttpRequest();
                let self = this

                xhr.upload.onprogress = function (event) {
                  if (event.lengthComputable) {
                    let percentComplete = (event.loaded / event.total) * 100;
                    self.$store.commit('SET_PERCENTAGE', {id: lessonId, percent: percentComplete})
                  }
                };

                xhr.upload.onload = function () {
                  self.$toast.success(`Видео ${fileName} успешно загружено`, {
                    position: 'top-right'
                  })

                  self.$store.commit('COMPLETE_UPLOADING', {id: lessonId})
                }

                xhr.upload.onerror = function () {
                  self.$toast.error(`Ошибка загрузки видео ${fileName}`, {
                    position: 'top-right'
                  })

                  self.$store.commit('COMPLETE_UPLOADING', {id: lessonId})
                }

                xhr.open('PUT', 'https://storage.yandexcloud.net/platfor-easy-code-bucket/' + this.selectedFileName, true)

                xhr.send(this.file)

                this.$modal.hide('edit-lesson')


А так же сделал предупреждение, если пользователь пытается закрыть или обновить вкладку
Мутации управления прогрессбаром во Vuex, возможно сразу несколько параллельных загрузок.
PUSH_UPLOADING(state, filename) {
            state.uploadingFiles.push(filename)
            window.onbeforeunload = () => {
                return false
            }
        },
        COMPLETE_UPLOADING(state, lesson) {
            state.uploadingFiles = state.uploadingFiles.filter(file => file.id !== lesson.id)
            if (state.uploadingFiles?.length) {
                window.onbeforeunload = () => {
                    return true
                }
            }
        },
        SET_PERCENTAGE(state, value) {
            let index = state.uploadingFiles.findIndex(i => i.id === value.id)
            state.uploadingFiles[index].percent = value.percent
        }
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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