Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 08.12.2021, 20:22
Аспирант
Отправить личное сообщение для developer_ Посмотреть профиль Найти все сообщения от developer_
 
Регистрация: 28.07.2011
Сообщений: 40

XMLHttpRequest как отправить ответ не дожидаясь приёма всех данных
Суть такова. Передаю файл на сервер. На сервере стоит ограничения на размер принимаемых файлов. Доступ к серверу у меня полный. Т.е. ответы я сам формирую - и поэтому могу сделать поведения сервера абсолютно любым.

Так вот. Я принимаю первый пакет данных. Выделяю заголовок и и ищу длину тела. Если длина тела больше разрешённой, то сразу отправляю ответ.

Провёл сотню экспериментов. Даже извращался с длиной принятых данных. Перед тем как ответ отослать.

Поведение браузера всегда одинаково - если я присылаю любой ответ до того как все данные были переданы то я получаю:
событие onreadystatechange
xhr.readyState = 4
xhr.status == 0
xhr.responseText - всегда пусто

Как по мне это какое то тупое поведение.

Я выставлял всевозможные статусы ответа вплоть до экзотических 413. Но xhr.status всегда 0.

Текст всегда xhr.responseText пустой - что бы я не отправлял.

Такое ощущение что браузер тупо по эксепшену вылетает - и даже не пытается обработать код ответа.

Я же хочу прислать сообщение что файл большой - и это сообщение отобразить пользователю.

Кто как решает подобную проблему?

Пока что напрашивается тупой метод - сохранить в сессии код ошибки и запрашивать его отдельным запросом. Но мне этот подход жутко не нравится.
Ответить с цитированием
  #2 (permalink)  
Старый 08.12.2021, 20:34
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,762

Ну значит после проверки принимать все, не записывая в файл, а потом посылать ответ, что файл большой и не записан.
Ответить с цитированием
  #3 (permalink)  
Старый 08.12.2021, 20:42
Аспирант
Отправить личное сообщение для developer_ Посмотреть профиль Найти все сообщения от developer_
 
Регистрация: 28.07.2011
Сообщений: 40

Этот вариант я тоже рассматривал. Но он мне тоже не нравится.
Ограничение на размер принимаемого файла сделан для защиты сервера от dos атак. Получается если кто то захочет передавать файлы в неограниченном количестве размером гигабайты - то такие сессии рубятся.
Поэтому принимать не вариант.

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

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

Сейчас пробую использовать fetch - посмотрю как там дела обстоят.
Ответить с цитированием
  #4 (permalink)  
Старый 08.12.2021, 20:44
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,762

Можно еще попробовать ограничить длину запроса на сервере.
У appache - LimitRequestBody
Тогда сам сервер будет посылать код ошибки, не вызывая скрипт.
Ответить с цитированием
  #5 (permalink)  
Старый 08.12.2021, 20:51
Аспирант
Отправить личное сообщение для developer_ Посмотреть профиль Найти все сообщения от developer_
 
Регистрация: 28.07.2011
Сообщений: 40

Сообщение от voraa Посмотреть сообщение
Можно еще попробовать ограничить длину запроса на сервере.
У appache - LimitRequestBody
Тогда сам сервер будет посылать код ошибки, не вызывая скрипт.
Как я говорил - я на сервере "царь и бог". Шутка. В общем сам формирую байтовый поток. Могу послать абсолютно что угодно. Посылаю разумеется корректные http ответы.

И получается - что мне послать браузеру (проверял на мозила и частично хром), что бы браузер мог принять ответ до того как отошлёт все данные.

Upd. дополню как происходит обрыв данных. Т.к. у меня есть полный доступ к приёмному сокету - я принимаю данные порциями. Собственно TCP так и работает. Принимаю данные до тех пор пока не придёт шапка - где я могу вычленить размер body. Далее данные не принимаю. На уровне TCP - висит статус что сервер больше не может принять данные. Клиент в данном случае браузер, на уровне TCP шлёт запросы на возможность передать оставшиеся данные.

Я в этот момент отправляю ответ и закрываю сокет.

Я это написал - потому как не уверен как корректно вообще прерывать отсылку данных с браузера.

Последний раз редактировалось developer_, 08.12.2021 в 21:01.
Ответить с цитированием
  #6 (permalink)  
Старый 08.12.2021, 21:05
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,762

Ну еще одна идея.
Ловить в браузере ошибку на XMLHttpRequest.upload;
Может при загрузке сработает событие error или abort
https://learn.javascript.ru/xmlhttpr...gress-otpravki
https://basicweb.ru/javascript/js_xm...est_upload.php
Ответить с цитированием
  #7 (permalink)  
Старый 08.12.2021, 21:13
Аспирант
Отправить личное сообщение для developer_ Посмотреть профиль Найти все сообщения от developer_
 
Регистрация: 28.07.2011
Сообщений: 40

error пробовал - бесполезное событие. Оно всегда вызывалось после onreadystatechange когда туда приходило
xhr.readyState = 4
xhr.status == 0
xhr.responseText - всегда пусто

Собственно в error было тоже самое.
Остальные события сейчас попробую.
Ответить с цитированием
  #8 (permalink)  
Старый 08.12.2021, 21:16
Аспирант
Отправить личное сообщение для developer_ Посмотреть профиль Найти все сообщения от developer_
 
Регистрация: 28.07.2011
Сообщений: 40

Ещё пробовал xhr.upload.onprogress - оно несколько раз вызывалось когда я экспериментировал с количеством принимаемых обязательных данных.

Собственно так оно и должно работать - приняли 10k - показали 10к

Но оно оказалось бесполезным в моей ситуации
Ответить с цитированием
  #9 (permalink)  
Старый 08.12.2021, 21:18
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,762

Нет, не xhr.onerror или xhr.onreadystatechange,
а
xhr.upload.onerror
или
xhr.upload.onabort
Ответить с цитированием
  #10 (permalink)  
Старый 08.12.2021, 21:23
Аспирант
Отправить личное сообщение для developer_ Посмотреть профиль Найти все сообщения от developer_
 
Регистрация: 28.07.2011
Сообщений: 40

результаты эксперимента:
load - вызывается только если все данные отправлены на сервер.

abort,loadend - вообще не вызываются при моей ситуации.

про error писал. Остальные события в xhr.upload - не подходят для ситуации.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
как убрать встроенные стили у всех дивов? Kvark Элементы интерфейса 3 08.08.2013 14:20
отправка всех данных store на сервер shepard90 ExtJS 1 03.04.2013 23:52
Как заставить выполняться обработчик после всех имеющихся обработчиков данного элемен Анатолий Саратовцев jQuery 2 08.10.2012 18:49
Двойная Фильтрация данных таблицы David0707 Общие вопросы Javascript 0 19.03.2012 13:00
Как изменить свойство css у всех элементов одного класса AlexJ Events/DOM/Window 7 19.03.2011 06:25