Js прочитать файл на сервере

Обновлено: 06.07.2024

На сервере есть текстовый файл. Используя JavaScript на клиенте, я хочу иметь возможность прочитать этот файл и обработать его. Формат файла на сервере не может быть изменен.

Как я могу получить содержимое файла в переменных JavaScript, так что я могу сделать эту обработку? Размер файла может быть до 3,5 МБ, но его можно легко обработать в кусках, скажем, в 100 строк (1 строка - 50-100 символов).

Ни одно из содержимого файла не должно быть видимым для пользователя; он увидит результаты обработки данных в файле.

Вы можете использовать скрытый фрейм, загрузить файл и проанализировать его содержимое.

Примечание. Чтобы это работало в браузере Chrome, вы должны запустить его с флагом --allow-file-access-from-files. кредит.

Загрузка этой гигантской капли данных не является отличным планом, но если вы должны здесь, очертите, как вы можете это сделать, используя jQuery $.ajax() .

Вам нужно использовать Ajax, который в основном отправляет запрос на сервер, а затем получает объект JSON, который вы конвертируете в объект JavaScript.

Если вы используете библиотеку jQuery, это может быть еще проще:

Сказав это, я настоятельно рекомендую вам не загружать файл с 3.5MB в JS! Это не очень хорошая идея. Выполняйте обработку на своем сервере, а затем возвращайте данные после обработки. Затем, если вы хотите получить новые данные, отправьте новый запрос Ajax, обработайте запрос на сервере, а затем верните новые данные.

Надеюсь, что это поможет.

Я использовал предложение Рафида об использовании AJAX.

Это сработало для меня:

Я не знаю, как это работает, но вам не нужно знать, как ваши тормоза работают, чтобы использовать их;)

Надеюсь, это поможет!

Для чтения файлов устройства используйте это:

Для чтения файла с сервера используйте:

Я действительно думаю, что ты об этом поступил неправильно. Попытка загрузить и проанализировать текстовый файл + 3Mb - это полное безумие. Почему бы не разобрать файл на стороне сервера, сохраняя результаты viva ORM в базе данных (ваш выбор, SQL хорош, но он также зависит от данных о ключевом значении контента, лучше работает на чем-то вроде CouchDB), затем используйте ajax для анализа данных на стороне клиента.

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

Посмотрите другие вопросы по меткам javascript ajax file-io или Задайте вопрос

Мнение о том, что JavaScript не умеет взаимодействовать с файловой системой, является не совсем верным. Скорее, речь идет о том, что это взаимодействие существенно ограничено по сравнению с серверными языками программирования, такими как Node.js или PHP. Тем не менее, JavaScript умеет как получать (принимать), так и создавать некоторые типы файлов и успешно обрабатывать их нативными средствами.

В этой статье мы создадим три небольших проекта:

  • Реализуем получение и обработку изображений, аудио, видео и текста в формате txt и pdf
  • Создадим генератор JSON-файлов
  • Напишем две программы: одна будет формировать вопросы (в формате JSON), а другая использовать их для создания теста

Получаем и обрабатываем файлы

Для начала создадим директорию, в которой будут храниться наши проекты. Назовем ее «Work-With-Files-in-JavaScript» или как Вам будет угодно.

В этой директории создадим папку для первого проекта. Назовем ее «File-Reader».

Создаем в ней файл «index.html» следующего содержания:


Здесь мы имеем контейнер-файлоприемник и инпут с типом «file» (для получения файла; мы будем работать с одиночными файлами; для получения нескольких файлов инпуту следует добавить атрибут «multiple»), который будет спрятан под контейнером.

Стили можно подключить отдельным файлом или в теге «style» внутри head:


Можете сделать дизайн по своему вкусу.

Не забываем подключить скрипт либо в head с атрибутом «defer» (нам нужно дождаться отрисовки (рендеринга) DOM; можно, конечно, сделать это в скрипте через обработку события «load» или «DOMContentLoaded» объекта «window», но defer намного короче), либо перед закрывающим тегом «body» (тогда не нужен ни атрибут, ни обработчик). Лично я предпочитаю первый вариант.

Откроем index.html в браузере:


Прежде чем переходить к написанию скрипта, следует подготовить файлы для приложения: нам потребуется изображение, аудио, видео, текст в формате txt, pdf и любом другом, например, doc. Можете использовать мою коллекцию или собрать свою.

Нам часто придется обращаться к объектам «document» и «document.body», а также несколько раз выводить результаты в консоль, поэтому предлагаю обернуть наш код в такое IIFE (это не обязательно):


Первым делом объявляем переменные для файлоприемника, инпута и файла (последний не инициализируем, поскольку его значение зависит от способа передачи — через клик по инпуту или бросание (drop) в файлоприемник):

Отключаем обработку событий «dragover» и «drop» браузером:


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

Обрабатываем бросание файла в файлоприемник:


Мы только что реализовали простейший механизм «dran'n'drop».

Обрабатываем клик по файлоприемнику (делегируем клик инпуту):


Приступаем к обработке файла:


Удаляем файлоприемник и инпут:


Способ обработки файла зависит от его типа:


Мы не будем работать с html, css и js-файлами, поэтому запрещаем их обработку:


Мы также не будем работать с MS-файлами (имеющими MIME-тип «application/msword», «application/vnd.ms-excel» и т.д.), поскольку их невозможно обработать нативными средствами. Все способы обработки таких файлов, предлагаемые на StackOverflow и других ресурсах, сводятся либо к конвертации в другие форматы с помощью различных библиотек, либо к использованию viewer'ов от Google и Microsoft, которые не хотят работать с файловой системой и localhost. Вместе с тем, тип pdf-файлов также начинается с «application», поэтому такие файлы мы будем обрабатывать отдельно:


Для остальных файлов получаем их «групповой» тип:


Посредством switch..case определяем конкретную функцию обработки файла:

Для чтения файла NodeJS необходимо использовать модуль под названием "fs". Приведём пример кода для считывания файла под названием "file.txt" и вывода его содержимого в консоль: Первым аргументом метода "readFileSync" передаётся абсолютный или относительный адрес файла, который необходимо считать. Второй параметр - это кодировка файла для считывания.

Наличие "Sync" в названии метода "readFileSync" означает, что используется синхронный метод чтения файла. То есть файл блокируется на время операции для всех пользователей. Мы использовали именно этот метод сейчас, потому что его легче реализовать (меньше кода)

В отличии от PHP, в котором запросы от пользователей обрабатываются параллельно, в NodeJS выполняется только одна копия кода. К примеру, если установить бесконечный цикл вывода данных (например, в групповом чате), то первый пользователь, который запустит скрипт увидит цикл с самого начала, а остальные только с времени своего входа (запроса к скрипту). Из-за наличия синхронности "Sync" код из примера выше будет выполняться для всех пользователей одновременно. Попробуем переписать его, чтобы сделать параллельное выполнение. Получится так: В этом примере чтение файла выполняется асинхронно! То есть если файл достаточно большой, то при выполнения кода примера сначала мы увидим в консоли строку "Тише, мыши, кот на крыше", а только потом содержимое файла. Обратите внимание на третий параметр функции "fs.readFile". В NodeJS часто используются callback функции, у которых в первом параметре указывается название переменно, куда попадает ошибка выполнения.

Запись файла

Для асинхронной записи данных в файл существует метод "writeFile" модуля "fs". При этом файл будет принудительно создан при отсутствии, либо вся информация будет удалена из него, если она есть. Первым параметром этой функции передаётся название файла, вторым данные для записи. При этом в третьем параметре необходимо передать callback функцию с единственным параметром - переменной, в которую запишется ошибка. Продемонстрируем простейший пример записи в файл: Обратите внимание, что во второй строчке этого примера callback функцию можно записать, опусти слово "function" и даже скобки вокруг (error). Но тогда надо поставить знак => (получится "стрелочная" функция). Чтобы получилось так: Если параметр только один, то круглые скобки и вовсе можно убрать (и нельзя если параметров несколько): Но обычно круглые скобки оставляют, чтобы было нагляднее, что это функция.

Если в первом параметре "writeFile" указать несуществующий путь (папку, которой нет), то будет возвращена ошибка. Потому что "writeFile" умеет создавать только файлы, но не папки.

Необходимые условия: Основы JavaScript (см. первые шаги, структурные элементы, объекты JavaScript), основы клиентских API
Задача: Узнать, как извлекать данные с сервера и использовать их для обновления содержимого веб-страницы.

В чем проблема?

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

A basic representation of a web site architecture

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

Появление Ajax

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

A simple modern architecture for web sites

Модель Ajax предполагает использование веб-API в качестве прокси для более разумного запроса данных, а не просто для того, чтобы браузер перезагружал всю страницу. Давайте подумаем о значении этого:

  1. Перейдите на один из ваших любимых сайтов, богатых информацией, таких как Amazon, YouTube, CNN и т.д., и загрузите его.
  2. Теперь найдите что-нибудь, например, новый продукт. Основной контент изменится, но большая часть информации, подобной заголовку, нижнему колонтитулу, навигационному меню и т. д., останется неизменной.

Это действительно хорошо, потому что:

  • Обновления страницы намного быстрее, и вам не нужно ждать перезагрузки страницы, а это означает, что сайт работает быстрее и воспринимается более отзывчивым.
  • Меньше данных загружается при каждом обновлении, что означает меньшее потребление пропускной способности. Это не может быть такой большой проблемой на рабочем столе в широкополосном подключении, но это серьёзная проблема на мобильных устройствах и в развивающихся странах, которые не имеют повсеместного быстрого интернет-сервиса.

Чтобы ускорить работу, некоторые сайты также сохраняют необходимые файлы и данные на компьютере пользователя при первом обращении к сайту, а это означает, что при последующих посещениях они используют локальные версии вместо загрузки свежих копий, как при первой загрузке страницы. Содержимое загружается с сервера только при его обновлении.

A basic web app data flow architecture

Основной запрос Ajax

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

Чтобы начать этот пример, создайте локальную копию ajax-start.html и четырёх текстовых файлов - verse1.txt, verse2.txt, verse3.txt и verse4.txt - в новом каталоге на вашем компьютере. В этом примере мы загрузим другое стихотворение (который вы вполне можете распознать) через XHR, когда он будет выбран в выпадающем меню.

Внутри элемента <script> добавьте следующий код. В нем хранится ссылка на элементы <select> и <pre> в переменных и определяется onchange обработчика событий, так что, когда значение select изменяется, его значение передаётся вызываемой функции updateDisplay() в качестве параметра.

Давайте определим нашу функцию updateDisplay() . Прежде всего, поставьте следующее ниже своего предыдущего блока кода - это пустая оболочка функции:

Мы начнём нашу функцию с создания относительного URL-адреса, указывающего на текстовый файл, который мы хотим загрузить и который понадобится нам позже. Значение элемента <select> в любой момент совпадает с текстом внутри выбранного <option> (если вы не укажете другое значение в атрибуте value) - например, «Verse 1». Соответствующий текстовый файл стиха является «verse1.txt» и находится в том же каталоге, что и файл HTML, поэтому будет использоваться только имя файла.

Тем не менее, веб-серверы, как правило, чувствительны к регистру, и имя файла не имеет символа "пробела". Чтобы преобразовать «Verse 1» в «verse1.txt», нам нужно преобразовать V в нижний регистр, удалить пробел и добавить .txt в конец. Это можно сделать с помощью replace () , toLowerCase () и простой конкатенации строк. Добавьте следующие строки внутри функции updateDisplay() :

Затем мы зададим тип ожидаемого ответа, который определяется как свойство responseType - как text . Здесь это не является абсолютно необходимым - XHR возвращает текст по умолчанию - но это хорошая идея, чтобы привыкнуть к настройке этого, если вы хотите получить другие типы данных в будущем. Добавьте следующее:

Получение ресурса из сети - это asynchronous операция, означающая, что вам нужно дождаться завершения этой операции (например, ресурс возвращается из сети), прежде чем вы сможете сделать что-либо с этим ответом, иначе будет выброшена ошибка. XHR позволяет вам обрабатывать это, используя обработчик события onload - он запускается при возникновении события load (en-US) (когда ответ вернулся). Когда это произойдёт, данные ответа будут доступны в свойстве response (ответ) объекта запроса XHR.

Добавьте следующее ниже вашего последнего дополнения. Вы увидите, что внутри обработчика события onload мы устанавливаем textContent poemDisplay (элемент <pre> ) в значение request. response .

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

Обслуживание вашего примера с сервера

Некоторые браузеры (включая Chrome) не будут запускать запросы XHR, если вы просто запускаете пример из локального файла. Это связано с ограничениями безопасности (для получения дополнительной информации о безопасности в Интернете, ознакомьтесь с Website security).

Чтобы обойти это, нам нужно протестировать пример, запустив его через локальный веб-сервер. Чтобы узнать, как это сделать, прочитайте Как настроить локальный тестовый сервер?

Fetch

Давайте преобразуем последний пример, чтобы использовать Fetch!

Сделайте копию своего предыдущего готового каталога примеров. (Если вы не работали над предыдущим упражнением, создайте новый каталог и внутри него создайте копии xhr-basic.html и четырёх текстовых файлов — verse1.txt, verse2.txt, verse3.txt и verse4.txt.)

Внутри функции updateDisplay() найдите код XHR:

Замените весь XHR-код следующим:

Загрузите пример в свой браузер (запустите его через веб-сервер), и он должен работать так же, как и версия XHR, при условии, что вы используете современный браузер.

Итак, что происходит в коде Fetch?

Прежде всего, мы вызываем метод fetch() , передавая ему URL-адрес ресурса, который мы хотим получить. Это современный эквивалент request.open() в XHR, плюс вам не нужен эквивалент .send() .

После этого вы можете увидеть метод .then() , прикреплённый в конец fetch() - этот метод является частью Promises - современная функция JavaScript для выполнения асинхронных операций. fetch() возвращает промис, который разрешает ответ, отправленный обратно с сервера, - мы используем .then() для запуска некоторого последующего кода после того, как промис будет разрешено, что является функцией, которую мы определили внутри неё. Это эквивалент обработчика события onload в XHR-версии.

Эта функция автоматически передаёт ответ от сервера в качестве параметра, когда обещает fetch() . Внутри функции мы берём ответ и запускаем его метод text() (en-US) , который в основном возвращает ответ как необработанный текст. Это эквивалент request.responseType = 'text' в версии XHR.

Вы увидите, что text() также возвращает промис, поэтому мы привязываем к нему другой .then() , внутри которого мы определяем функцию для получения необработанного текста, который выполняет text() .

Внутри функции внутреннего промиса мы делаем то же самое, что и в версии XHR, - устанавливаем текстовое содержимое <pre> в текстовое значение.

Помимо промисов

Промисы немного запутывают первый раз, когда вы их встречаете, но не беспокойтесь об этом слишком долго. Через некоторое время вы привыкнете к ним, особенно, когда вы узнаете больше о современных JavaScript-API. Большинство из них в большей степени основаны на промисах.

Давайте посмотрим на структуру промисов сверху, чтобы увидеть, можем ли мы ещё немного понять это:

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

Но имеет смысл называть параметр тем, что описывает его содержимое!

Теперь давайте сосредоточимся только на функции:

Объект ответа имеет метод text() (en-US) , который берёт необработанные данные, содержащиеся в теле ответа, и превращает его в обычный текст, который является форматом, который мы хотим в нем А также возвращает промис (который разрешает полученную текстовую строку), поэтому здесь мы используем другой .then() , внутри которого мы определяем другую функцию, которая диктует что мы хотим сделать с этой текстовой строкой. Мы просто устанавливаем свойство textContent элемента <pre> нашего стихотворения равным текстовой строке, так что это получается довольно просто.

Также стоит отметить, что вы можете напрямую связывать несколько блоков промисов ( .then() , но есть и другие типы) на конце друг друга, передавая результат каждого блока следующему блоку по мере продвижения по цепочке , Это делает промисы очень мощными.

Следующий блок делает то же самое, что и наш оригинальный пример, но написан в другом стиле:

Многие разработчики любят этот стиль больше, поскольку он более плоский и, возможно, легче читать для более длинных цепочек промисов - каждое последующее промис приходит после предыдущего, а не внутри предыдущего (что может стать громоздким). Единственное отличие состоит в том, что мы должны были включить оператор return перед response.text() , чтобы заставить его передать результат в следующую ссылку в цепочке.

Какой механизм следует использовать?

Это действительно зависит от того, над каким проектом вы работаете. XHR существует уже давно и имеет отличную кросс-браузерную поддержку. Fetch and Promises, с другой стороны, являются более поздним дополнением к веб-платформе, хотя они хорошо поддерживаются в браузере, за исключением Internet Explorer и Safari (которые на момент написания Fetch были доступны в своём предварительный просмотр технологии).

Если вам необходимо поддерживать старые браузеры, тогда может быть предпочтительным решение XHR. Если, однако, вы работаете над более прогрессивным проектом и не так обеспокоены старыми браузерами, то Fetch может быть хорошим выбором.

Вам действительно нужно учиться - Fetch станет более популярным, так как Internet Explorer отказывается от использования (IE больше не разрабатывается, в пользу нового браузера Microsoft Edge), но вам может понадобиться XHR ещё некоторое время.

Более сложный пример

Чтобы завершить статью, мы рассмотрим несколько более сложный пример, который показывает более интересные применения Fetch. Мы создали образец сайта под названием The Can Store - это вымышленный супермаркет, который продаёт только консервы. Вы можете найти этот пример в прямом эфире на GitHub и посмотреть исходный код.

A fake ecommerce site showing search options in the left hand column, and product search results in the right hand column.

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

Существует довольно много сложного кода, который включает фильтрацию продуктов по категориям и поисковым запросам, манипулирование строками, чтобы данные отображались правильно в пользовательском интерфейсе и т.д. Мы не будем обсуждать все это в статье, но вы можете найти обширные комментарии в коде (см. can-script.js).

Однако мы объясним код Fetch.

Первый блок, который использует Fetch, можно найти в начале JavaScript:

Это похоже на то, что мы видели раньше, за исключением того, что второй промис находится в условном выражении. В этом случае мы проверяем, был ли возвращённый ответ успешным - свойство response.ok (en-US) содержит логическое значение, которое true , если ответ был в порядке (например, 200 meaning "OK") или false , если он не увенчался успехом.

Если ответ был успешным, мы выполняем второй промис - на этот раз мы используем json() (en-US) , а не text() (en-US) , так как мы хотим вернуть наш ответ как структурированные данные JSON, а не обычный текст.

Вы можете проверить сам случай отказа:

Второй блок Fetch можно найти внутри функции fetchBlob() :

Это работает во многом так же, как и предыдущий, за исключением того, что вместо использования json() (en-US) мы используем blob() (en-US) - в этом случае мы хотим вернуть наш ответ в виде файла изображения, а формат данных, который мы используем для этого - Blob - этот термин является аббревиатурой от« Binary Large Object »и может в основном использоваться для представляют собой большие файловые объекты, такие как изображения или видеофайлы.

После того как мы успешно получили наш blob, мы создаём URL-адрес объекта, используя createObjectURL() . Это возвращает временный внутренний URL-адрес, указывающий на объект, указанный в браузере. Они не очень читаемы, но вы можете видеть, как выглядит, открывая приложение Can Store, Ctrl-/щёлкнуть правой кнопкой мыши по изображению и выбрать опцию «Просмотр изображения» (которая может немного отличаться в зависимости от того, какой браузер вы ). URL-адрес объекта будет отображаться внутри адресной строки и должен выглядеть примерно так:

Вызов: XHR версия the Can Store

Мы хотели бы, чтобы вы решили преобразовать версию приложения Fetch для использования XHR в качестве полезной части практики. Возьмите копию ZIP файла и попробуйте изменить JavaScript, если это необходимо.

Некоторые полезные советы:

Примечание: Если у вас есть проблемы с этим, не стесняйтесь сравнить свой код с готовой версией на GitHub (см. исходник здесь, а также см. это в действии).

Резюме

Это завершает нашу статью по извлечению данных с сервера. К этому моменту вы должны иметь представление о том, как начать работать как с XHR, так и с Fetch.

Смотрите также

Однако в этой статье обсуждается много разных тем, которые только поцарапали поверхность. Для получения более подробной информации по этим темам, попробуйте следующие статьи:

Читайте также: