У меня есть сервер, написанный на Node.js, и веб-клиент, работающий в браузере. Клиент должен загрузить и загрузить некоторые файлы с сервера и на сервер. Сервер не тот, который изначально доставляет клиента, поэтому мы имеем междоменную ситуацию здесь.
Сервер использует промежуточное программное обеспечение cors для обеспечения междоменных запросов. Поскольку я также использую несколько пользовательских заголовков, я использую его с такой конфигурацией:
api.use(cors({
origin: '*',
allowedHeaders: [ 'content-type', 'authorization', 'x-metadata', 'x-to' ],
exposedHeaders: [ 'content-type', 'content-disposition', 'x-metadata' ]
}));
Напротив, клиент использует axios , и код для загрузки файла выглядит так:
await axios({
method: 'post',
url: 'https://localhost:3000/api/v1/add-file',
data: content,
headers: {
// ...
}
});
Пока что все работает, как и ожидалось, и особенно работает с CORS.
Теперь я хотел бы отследить ход загрузки, и поэтому я добавляю обратный вызов onUploadProgress
к вызову axios
, как предложено в его документации :
await axios({
method: 'post',
url: 'https://localhost:3000/api/v1/add-file',
data: content,
headers: {
// ...
},
onUploadProgress (progressEvent) {
console.log({ progressEvent });
}
});
Если я сейчас запустил клиент, загрузка все еще работает - но обратный вызов onUploadProgress
никогда не вызывается. Я читал, что не все браузеры поддерживают это (внутренне это просто привязывается к событию onprogress
базового объекта XmlHttpRequest
), но последний Chrome должен быть в состоянии сделать это (и если я попробую другую настройку, где CORS не участвует, кажется, все работает). Поэтому я предполагаю, что это проблема CORS.
У меня есть read , что как только вы добавите прослушиватель к событию onprogress
, будет отправлен предварительный запрос. Это, в свою очередь, означает, что сервер должен принимать OPTIONS
запросов. Для этого я добавил следующий код на сервере: перед вышеупомянутым вызовом api.use
:
api.options('*', cors({
origin: '*',
methods: [ 'GET', 'POST' ],
allowedHeaders: [ 'content-type', 'authorization', 'x-metadata', 'x-to' ],
exposedHeaders: [ 'content-type', 'content-disposition', 'x-metadata' ],
optionsSuccessStatus: 200
}));
Результат: загрузка все еще работает, но событие onUploadProgress
не инициируется. Поэтому я предполагаю, что мне чего-то не хватает, связанного с CORS. Вопрос только в том: чего мне не хватает?
Я также попытался повторно запустить ту же настройку с большим файлом (почти 2 ГБ вместо нескольких КБ), но результат тот же. У кого-нибудь есть идеи, что я здесь делаю не так?
UPDATE
Чтобы ответить на некоторые комментарии: во-первых, моя axios
версия 0.18.0
, поэтому я использую последний доступный стабильный выпуск.
Исходный код для сервера можно найти в репозитории thenativeweb / wolkenkit-depot . Часть CORS настроена здесь . Обратите внимание, что это немного отличается от версии, которую я разместил выше, так как я сделал несколько локальных изменений. Однако это то место, с которым вам нужно иметь дело.
Чтобы построить сервер, вам нужно иметь Node.js и Docker. Затем выполните:
$ npm install
$ npx roboter build
Это приведет к созданию нового образа Docker, который содержит код сервера (этот образ Docker вам понадобится для запуска клиентских тестов, указанных ниже). Обратите внимание, что если вы что-то изменили на сервере, вам придется заново создать этот образ Docker.
Клиент может быть найден в хранилище thenativeweb / wolkenkit-depot-client-js , в ветке Issue-145-Notifiy-about-progress-when-uploading-or-download -файлы .
В файле DepotClient.js Я добавил прослушиватель событий в onUploadProgress
, который должен просто вызвать исключение (что, в свою очередь, должно сделать довольно очевидным, что событие было вызвано).
Этот код затем запускается этим тестом (есть еще тесты для этого, но это один из них), что должно привести к исключению, но это не так.
Чтобы снова запустить тесты, у вас должны быть установлены Node.js и Docker, , и вы должны собрать сервер, как описано выше . Затем используйте следующие команды для запуска тестов от вашего имени:
$ npm install
$ npx roboter test --type integration
Я ожидаю, что должен подать хотя бы один из addFile
тестов. На самом деле все они становятся зелеными, что означает, что сама загрузка работает отлично, но событие onUploadProgress
никогда не вызывается. На тот случай, если вам интересно, в какой среде выполняются тесты: я использую кукольника, который является Chrome без головы.