Отменить загрузку файла js
Я использую метод dojo.io.iframe.send для отправки файла на свой сервер. Я хочу предоставить способ, которым пользователь может отменить отправку, когда она уже выполняется, в случае, если она занимает слишком много времени или пользователь понимает, что отправил неправильный файл.
Я не могу придумать, как это сделать. Я мог бы использовать тайм-аут, чтобы прервать отправку, если это занимает много времени (то есть сервер не отвечает быстро), но это не то, что я хочу. Я хочу завершить работу каждый раз, когда пользователь делает жест (например, нажимает кнопку «Отмена».
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно.
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей.
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то.
Объединяем потоки
Сейчас наш код ничем не отличается от того, который бы мы написали, используя addEventListener. Да, он работает, но если мы оставим его таким, то потеряем те преимущества, которые открывает перед нами RxJS.
Что мы можем сделать? Распишем последовательность шагов для выгрузки файла:
- Выбор файла
- Нажатие кнопки uploadBtn
- Извлечение файла из input.files
- Выгрузка файла
Данный код очень похож на последовательность тех инструкций, что мы описали выше. Пользователь выбирает файл, срабатывает switchMap и мы подписываемся на uploadBtn. Но дальше ничего не произойдет.
switchMap пропускает во внешний поток только те значения, которые генерирует fromEvent(uploadBtn, 'click').Чтобы выгрузка файлов началась, нужно выполнить вторую инструкцию, а именно — нажать на uploadBtn. Затем отработает метод map, который извлечет файл из массива, и уже в subscribe произойдет вызов метода upload.
Самое интересное здесь то, что последовательность инструкций не нарушаема. Чтобы сработала функция upload, нужно, чтобы перед этим сработало событие 'change'.
Но все же одна проблема осталась. Пользователь может выбрать файл, а затем отменить свой выбор. И тогда при попытке выгрузки файла, мы передадим в функцию upload — undefined. Чтобы избежать подобной ситуации, нам следует добавить проверку:
Подготовка
Для начала нам потребуется сервер, который может принимать запросы на загрузку файлов. Для этого может подойти любой сервер, я для статьи буду использовать node.js в связке с express и multer:
Теперь создадим html страничку, на которой мы разместим все необходимые элементы:
Сейчас на страничке у нас есть 4 элемента, с которыми пользователь будет взаимодействовать:
- Input с типом file, чтобы пользователь смог выбрать файл для выгрузки
- Кнопка upload, при нажатии на которую мы начнем выгрузку
- Кнопка cancel, которая будет отменять загрузку
- Progress bar со стартовой шириной 0. В процессе выгрузки мы будем менять его ширину
Выглядеть все это должно примерно так:
Работаем с xhr
Пора реализовать самое сложное — процесс выгрузки. Я буду показывать его на примере работы с xhr, так как fetch, на момент написания статьи, не умеет отслеживать прогресс выгрузки.
Так как на серверной стороне я использую multer, то передавать файл мне придется внутри формы(multer принимает данные только в таком формате). Для этого я написал функцию createFormData:
Теперь у нас есть рабочий пример. Но он содержит пару недостатков:
- Нет возможности отменить загрузку
- Если нажать на кнопку uploadBtn n раз, то у нас откроется n параллельных соединений на выгрузку одного файла
Обратите внимание на возвращаемую внутри Observable стрелочную функцию. Данный метод будет вызван в момент отписки и отменит выгрузку.
Поместим вызов upload в switchMap:
Теперь, если пользователь нажмет на кнопку выгрузки еще раз, то предыдущий запрос будет отменен, но создастся новый.
Решение
Файл только подготавливается к отправке. Но пока ещё никуда не улетает.
Как сбросить поле написали выше.
Js и type="data" в input
Здравствуйте. Может кто поможет - есть на сайте кредитный калькулятор кем-то написанный. В.
Как запрограммировать действие на кнопку "Отмена"?
Здравствуйте! Как запрограммировать действие на кнопку "Отмена"? Какой командой это можно записать.
Как сделать "Method expression is Function type"?
let newObj = Object.create(rabbit, < own: < value: 'smth' >, actionMove:
Вывод двухмерного "input" массива через document.write
Здравствуйте, есть функция создающая двухмерный массив input типа number,но выводит функция на.
Прошло много времени с тех пор, как я написал свою последнюю статью по основам RxJS. В комментариях меня попросили показать более сложные примеры, которые могут пригодиться на практике. Поэтому я решил немного разбавить теорию и сегодня мы поговорим про выгрузку файлов.
Что мы будем делать?
- Напишем небольшую страничку, на которой пользователь сможет выбрать файл для загрузки его на сервер
- Добавим progress bar, чтобы отображался прогресс загрузки файла
- Добавим возможность отменить загрузку нажатием на кнопку отмены
Для понимания данной статьи вам потребуются базовые знания RxJS. Что такое Observable, операторы, а так-же HOO операторы
Не будем тянуть кота за хвост и сразу перейдем к делу!
Решение
Всё — поток
Чтобы сказать браузеру, какой файл нужно выбрать, пользователь должен кликнуть по кнопке «Choose file». После этого откроется диалоговое окно вашей операционной системы, где отобразится дерево папок. После выбора файла браузер загрузит всю необходимую информацию о нем.
Как нам понять, что пользователь выбрал файл? Для этого существует событие «change». После срабатывания события мы можем обратиться к массиву files в input’е, куда и будут записаны данные файла.
Как же нам слушать событие «change»? Можно воспользоваться методом addEventListener и работать с ним. Но мы работаем с RxJS, где любое событие может быть представлено как поток:
Добавим функцию upload, которая будет выгружать файл на сервер. Пока оставим ее тело пустым:
Функция upload должна вызываться после нажатия на кнопку uploadBtn:
Ответы 4
По соображениям безопасности JavaScript не может даже получить доступ к отправляемому вами файлу. Все загрузки файлов выполняются с использованием формы и обрабатываются напрямую браузером. Насколько мне известно, нет прямого интерфейса для отслеживания процесса загрузки или способа повлиять на нее (например, отменить ее).
Уход может помочь, но прерывать передачу или нет - это все еще зависит от браузера - для этого нет спецификации.
Подводя итог: невозможно сделать это надежным в JavaScript переносимым способом. Это означает, что Dojo не предоставляет эту функциональность.
Привет, я понимаю, что это довольно поздний ответ, поэтому я надеюсь, что вам или кому-то, кто наткнулся здесь через Google, это пригодится.
Это возможно для отмены загрузки файла в iFrame, в Firefox вы можете вызвать метод window.stop() в iFrame. IE, однако, не имеет этого метода, но поставляется с execCommand("Stop") , однако, поскольку ручное нажатие остановки даже не работает, остановка по сценарию тоже не работает.
Мои первые попытки включали установку местоположения iFrame на about:blank , к сожалению, безрезультатно. Однако при переходе к источнику с телом отменит iFrame POST!
Несколько примечаний: (1) Элемент iframe хранится в частном свойстве dojo.io.iframe._frame.
(2) execCommand ("Stop") вызывается как dojo.io.iframe._frame.contentDocument.execCommand ("Stop") в iframe (для IE).
(3) window.stop () вызывается как dojo.io.iframe._frame.contentWindow.stop () в iframe (для других браузеров)
(4) другие браузеры (Firefox, Chrome, Safari, Opera) отменяют загрузку таким же образом при удалении элемента формы из документа и при вызове contentWindow.stop () в iframe.
Друг просто перезагрузил веб-страницу, когда кнопка отмены была предварительно загружена (я думаю, вызвав функцию document.location.refresh). Существует также способ мониторинга прогресса загрузки (с индикатором выполнения), но он зависит от сервера (в случае, если я видел, это был модуль apache, тогда вы должны были бы опросить прогресс по указанной ссылке и серверу вернул бы прогресс).
Итак, я понимаю, что это действительно старый пост (4 года!), На который я отвечаю. Но я обнаружил это, когда искал в Google ответ, который, оглядываясь назад, должен был быть очевидным, но не получил ответа ни здесь (ни где-либо еще, что я искал). Итак, ради очередного бедняги:
Если (как и я) вы не заботитесь о фактической остановке передачи файла, а просто хотите позволить dojo.io.iframe ДВИГАТЬСЯ с жизнью (эффективно отменяя с точки зрения пользователя), вы можете просто проигнорировать результат отложенных обратных вызовов. Однако, если вы также хотите загрузить дополнительные вещи через dojo.io.iframe , вы также должны сделать так, чтобы этот dojo.io.iframe также игнорировал результат. Досадно просто . вызов dojo.io.iframe.send() возвращает deferred. Если вы хотите отменить загрузку, чтобы dojo.io.iframe выполнял последующие вызовы отправки в очереди (поскольку он может делать только по одному за раз), вам просто нужно вызвать .cancel() на отложенном, который вернулся из отправки, которая в настоящее время выполняется. .
Теперь пользователь нажимает кнопку отмены где-то, потому что загрузка занимает слишком много времени или он понял, что не собирался загружать выбранный файл. Мы не хотим ждать, пока будет произведена первая передача файла, потому что нас больше не волнует результат передачи.
Вызов отмены в dfd позволит немедленно выполнить второй вызов send() . если вы посмотрите в fiddler, вы увидите, что вторая загрузка теперь начинается немедленно, вместо того, чтобы ждать завершения первой (отмененной), как это было бы без вызова .cancel() в отложенном режиме.
Без отмены первого отложенного вызова dojo.io.iframe будет продолжать послушно ожидать результата первой загрузки, тем самым блокируя любые последующие поставленные в очередь вызовы send() , ожидающие обработки через dojo.io.iframe .
Как отменить загрузку файла ? Требуется реализовать условный крестиr при нажатии на который input подготовленный для загрузки сбросится на то состояние что было до выбора файла ?
То есть есть обычная форма, в ней обычный .
Что происходит когда мы выбираем какой0то файл ? Как привести это что-то в изначальное состояние ? Допустим я рядом добавлю крестик, но какие данные потом менять скриптом по нажатию по нему ?
Не нашел подобной инфы нигде (
Ошибка при стилизации input[type="file"] с добавлением JS
Здравствуйте! Новичок в JS поэтому очень нужна помощь. Есть такой маленький код JS: <script.
input type="number" Запретить ввод нулей
Здраствуйте, в input type="number" можно ввести например 001, скажите пожалуйста как сделать так.
Переделать скрипт под
Есть 2 блока выбора <fieldset> <legend>Крупный заполнитель:</legend> <div.
Input type="text" чтоб курсор при клике был в начале, как?
А то если щас кликнуть то он будет в том месте где кликнули, так телефон неудобно вводить. Причем.
Заключение
RxJS очень мощный инструмент в руках разработчика. В его арсенале есть огромнейший набор операторов на все случаи жизни. К сожалению, из-за этого порог входа в данную технологию довольно высок. И часто, люди по незнанию начинают писать свои «велосипеды», из-за чего код становится трудно поддерживаемым.
Поэтому, хочется пожелать всем читателям, не стоять на месте и не бояться экспериментировать. Изучайте RxJS. Вдруг вы наткнетесь на оператор, который может превратить 10 строчек кода в одну. Или поможет сделать код чуточку понятней.
Из области фантастики конечно, но вдруг…
Понятно что можно остановить загрузку всей страницы stop() и тогда все загрузки тоже отвалятся,
но это не то что нужно, нужно сказать стоп конкретной картинке если она слишком долго грузится.
Решение найдено.
Вот его автор paaashka
Реально помог довести наш скрипт до идеала.
Потратил на меня кучу времени но добил таки его, на чистом JS
Оценить 4 комментария
3) execCommand(«Stop», false); не подходит, если и будет работать то только в IE.
4) img.fireEvent(«abort»); не подходит, если и будет работать то только в IE.
5) Скрипт стоит на разных сайтах/доменах отличных от сервера на котором расположена картинка.
А если для картинки динамически создавать iframe с ней, и если не пришло событие из айфрейма о том, что картинка загрузилась, то удалять айфрейм вместе с картинкой? Сейчас попробовал — при удалении айфрейма, загрузка картинки останавливается.
Я ждал такое предложение :-) и даже пробовал, но у меня не получилось корректно это сделать, можно пример кода, круто если не jQuery
У меня даже была мысль грузить картинку в iframe и потом там уже говорить stop() но я не уверен что это сработало бы, а проверить не получилось, что то я не так делал там.
IE всё-таки не так прост оказался. Пока не смог для него нормальное решение сделать, он продолжает грузить iframe. Завтра ещё попробую, если что, напишу в личку.
Кажется получилось :) Непричёсанные исходники на смеси jQ и чистого js можно взять здесь. Закинуть на сервер и запустить index.php. Увеличив sleep в img.php до 4-5 секунд, можно увидеть, что загрузка файла отменяется.
Ещё есть куда дорабатывать, но идея кажется правильной.
Огоо! Это мне на двое суток разбиратся, но действительно вроде работает. Теперь буду думать как из этого сделать чистый js…
Я думал код будет слегка прощее :-))
Можно попробовать два варианта.
Первый, очевидный, что-то сделать с самой картинкой (img), изменить атрибут src, преобразовать в другой тег. Но скорее всего это не работает, поэтому вы и спрашиваете.
Не понял как мне это поможет, мне нужно отстрелить картинку если сервер или канал упали дабы у клиентов сайты не ждали ответа от сервера.
Можно сделать stop() но для всей страницы и если там видео грузилось к примеру то ему будет хана как и всему что не успело.
3. Если запрос выполнился без выпадения таймаута, значит картинка загрузилась в кеш. В противном случае картинка недоступна.
Как я сделаю ajax-запрос с другого домена/сайта на свой сервер?
Или я вас не правильно понимаю или известными методами это невозможно.
Зачем вас делать запрос с другого сайта? Ваша страница images.html (предположим) лежит на том же сервере что и скрипт подгружающий изображения. Скорее всего вы не понимаете, я вам говорю о действительно рабочем варианте, если браузеры кешируют так как я предполагаю.
Вы говорите что работали 2 дня, а сейчас ночь. Наверное вам лучше пойти спать, и утром посмотреть на то что я предлагаю со свежими силами. :-)
Я не очень понял причему тут кэширование.
У меня там вообще уникальные префиксы генерятся гетзапросом.
Я говорю что вижу, если браузер запросил картинку то он сволочь будет её грузить и плевать ему на мои действия.
Если сервер на который мы обращаемся упал или медленно отвечает, то браузер будет ждать этот файл.
Если у меня есть сценарий, загружаемый на мою страницу, который я не могу удалить (это очень большое корпоративное приложение, код с тех пор был потерян/похоронен), есть способ отменить сценарий от загрузки/выполнения браузера?
Мой вопрос в том, что я могу поместить в MyScriptCanceller.js что предотвратит загрузку браузера или выполнение MyBadScriptFile.js ?
Изменение: Или есть ли другой способ манипулирования ответом на то, где этот скрипт можно удалить или отключить в любой момент?
Нет. Файлы Javascript запускаются в порядке. Это означает, что содержимое третьего файла не будет выполнено до тех пор, пока не будет выполнено содержимое первого и второго файлов. И как только код был выполнен, вы не можете его отменить.
Если вы уверены, никто не будет нуждаться в javascript, почему бы не комментировать/опорожнять источник? Итак, файл будет загружен, но он не будет иметь никаких дополнительных эффектов? Если у вас нет доступа к источнику, попытка перебора будет заключаться в перехвате процесса доставки html и препроцессе html, чтобы исключить нежелательный javascript или перепроектировать скомпилированный код.
PS: Как я видел из ваших комментариев - у вас нет доступа к источнику. Это осложняет ситуацию.
Я бы предложил использовать приложение/плагин, например firebug, чтобы найти, где на странице загружается сценарий, и закомментировать скрипт (если его нельзя удалить).
Наличие другого скрипта никогда не будет отменять загрузку ранее инициированного скрипта, если он не будет загружен асинхронно (AJAX). Если это факт, он добавит только время загрузки, хотя и не очень, если это небольшой файл.
Это может быть немного работы, но я думаю, что ваш лучший выбор по-прежнему заключается в поиске и поиске исходного местоположения сценария с длинной загрузкой.
Может быть, вы могли бы MyScriptCanceller.js динамически создать третью ссылку, если какое-то условие выполнено? Если условие не выполняется, оно просто не создаст третьего js файла.
Progress bar
Осталось добавить progress bar. Для отслеживания прогресса нам понадобится определить метод xhr.upload.onprogress. Данный метод вызывается при возникновении события ProgressEvent. Объект события содержит в себе несколько полезных для нас свойств:
- lengthComputable — если true, значит, что нам известен полный размер файла(в нашем случае всегда true)
- total — общее количество байт
- loaded — количество отосланных байт
Теперь upload выплевывает в поток состояние выгрузки. Осталось только написать функцию, которая будет менять свойства style у элемента progressBar:
Небольшой совет: чтобы ваши файлы локально выгружались не так быстро, включите настройку «Fast 3G» или «Slow 3G» во вкладке «Performance» в Chrome devtools.
Доводим до ума
Мы получили полноценное рабочее приложение. Осталось добавить пару штрихов. Сейчас при нажатии на кнопку uploadBtn мы отменяем предыдущую выгрузку и начинаем новую. Но у нас уже есть кнопка отмены.
Хочется, чтобы кнопка uploadBtn не реагировала на последующие нажатия, пока мы не выгрузили файл(или пока мы не отменили выгрузку). Что можно предпринять?
Можно вешать атрибут disable, пока процесс выгрузки не завершится. Но есть другой вариант — оператор exhaustMap. Данный оператор будет игнорировать новые значения из внешнего потока, пока внутренний поток не будет завершен. Заменим switchMap на exhaustMap:
И вот теперь можно считать наше приложение законченным. Немного рефакторинга и получаем финальный вариант:
Мой вариант я выложил здесь.
Пример приложения на Angular можно найти здесь.
Отменяем запрос по клику
У нас еще осталась кнопка calcelBtn. Мы должны реализовать отмену запроса. Здесь нам поможет оператор takeUntil.
takeUntil переводится как “бери пока”. Данный оператор забирает значения из внешнего потока и отдает их дальше по цепочке. До тех пор, пока внутренний поток существует и ничего не генерирует. Как только внутренний поток сгенерирует значение — takeUntil вызовет метод unsubscribe и отпишется от внешнего потока.
Прежде чем добавить оператор, нужно определить, от какого потока мы хотим отписаться. Нас интересует upload, так как необходимо завершить только выгрузку файла, т.е. отписаться от внутреннего потока:
Читайте также: