Как сохранить файл на сервере node js

Обновлено: 03.07.2024

Хранилище объектов – удобный и масштабируемый способ хранения и обслуживания статических ресурсов, таких как аудио, изображения, текст, PDF-файлы и другие типы неструктурированных данных. Облачные провайдеры предлагают хранилища объектов в дополнение к традиционным локальным или блочным хранилищам, которые используются для хранения динамических файлов приложений и баз данных.

Данный мануал поможет создать приложение Node.js, которое будет выгружать файлы в хранилище объектов путем отправки формы в интерфейсе веб-сайта.

Требования

  • Хранилище объектов, access key и secret key.
  • Установленные Node.js и npm. Чтобы установить правильную версию, посетите эту ссылку.

Добавление ключей

Для подключения к хранилищу объектов можно использовать AWS SDK для JavaScript в Node.js.

Сначала нужно создать файл учетных данных и поместить в него access key и secret key, который вы получили при создании своего хранилища. Файл будет находиться в

/.aws/credentials на Mac и Linux или C:\Users\USERNAME\.aws\credentials в Windows. Если ранее вы уже сохранили учетные данные AWS, вы можете прочитать о поддержке нескольких наборов учетных данных здесь.

Откройте командную строку, перейдите в каталог Users как пользователь sudo и создайте файл с расширением .aws по имени credentials.

sudo mkdir .aws && touch .aws/credentials

Откройте файл и вставьте в него такой код (заменив your_access_key и your_secret_key своими данными).

[default] aws_access_key_id=your_access_key
aws_secret_access_key=your_secret_key

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

Установка зависимостей Node.js

Для начала создайте каталог, в который вы хотите поместить приложение Node.js, и перейдите в этот каталог. В этом мануале проект будет храниться в node-app в каталоге sites.

mkdir sites/node-app && cd sites/node-app

Создайте файл package.json для проекта. Вставьте в него такой код:

"name": "node-app",
"version": "1.0.0",
"main": "server.js",
"scripts": "start": "node server.js"
>,
"license": "MIT"
>

Этот базовый файл package.json определяет имя, номер версии и лицензию вашего приложения. Поле scripts позволяет запустить сервер Node.js, набрав npm start вместо node server.js.

Команда npm install установит все зависимости:

npm install aws-sdk express multer multer-s3

После запуска этой команды файл package.json должен обновиться. Эти зависимости помогут нам подключиться к API хранилища объектов, создать веб-сервер и обрабатывать загрузки файлов.

Теперь можно настроить сервер и фронт-энд.

Фронт-энд приложения

Для начала нужно создать файлы видов приложения. Это то, что пользователь увидит на фронт-энде. Создайте в своем проекте каталог public с файлами index.html, success.html и error.html. Все три этих файла будут иметь представленный ниже скелет HTML с разным содержимым в body. Добавьте следующий код в каждый файл.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Object Storage Tutorial</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- contents will go here -->
</body>
</html>

.
<h1>Something went wrong!</h1>
<p>File was not uploaded successfully.</p>
.

В index.html нужно создать форму HTML с multipart/form-data. Она будет состоять из input и кнопки отправки.

.
<h1>Object Storage Tutorial</h1>
<p>Please select a file and submit the form to upload an asset to your object storage.</p>
<form method="post" enctype="multipart/form-data" action="/upload">
<label for="file">Upload a file</label>
<input type="file" name="upload">
<input type="submit" >
</form>
.

Теперь создайте файл style.css и добавьте в него простой стиль CSS.

Настройка среды Express

Все файлы для фронт-энда приложения готовы, но в настоящее время нет настроенного сервера для их просмотра. Настройте сервер Node и фреймворк Express.

В корневом каталоге проекта создайте файл server.js. Сначала загрузите четыре зависимости приложения с помощью require(). Направьте приложение через экземпляр app.

// Load dependencies
const aws = require('aws-sdk');
const express = require('express');
const multer = require('multer');
const multerS3 = require('multer-s3');
const app = express();

Поскольку фронт-энд находится в каталоге public, добавьте его в конфигурацию:

.
// Main, error and success views
app.get('/', function (request, response) response.sendFile(__dirname + '/public/index.html');
>);
app.get("/success", function (request, response) response.sendFile(__dirname + '/public/success.html');
>);
app.get("/error", function (request, response) response.sendFile(__dirname + '/public/error.html');
>);

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

.
app.listen(3001, function () console.log('Server listening on port 3001.');
>);

Сохраните файл server.js и запустите сервер. Для этого нужно выполнить команду node server.js или npm start (сокращение, которое вы настроили ранее в файле package.json).

npm start
> node server.js
Server listening on port 3001.

Object Storage Tutorial
Please select a file and submit the form to upload an asset to your object storage.

Загрузка файла в хранилище с помощью Multer

Теперь, когда серверная среда работает корректно, нужно интегрировать формы с Multer и Multer S3 для загрузки файла в хранилище объектов.

Вы можете использовать метод new aws.S3() для подключения к клиенту Amazon S3. Для использования вашего хранилища объектов нужно установить новую конечную точку. В данном мануале используется условная точка nyc3.

Перейдите в начало файла server.js и вставьте в него следующий код после объявления const:

Используя пример из документации multer-s3, создайте функцию upload, установив в свойстве bucket уникальное имя вашего хранилища. Указав public-read в acl, вы сделаете все файлы в хранилище общедоступными; оставив этот параметр по умолчанию, вы сделаете файлы приватными, и они не будут доступны из Интернета.

.
// Change bucket property to your Object Storage name
const upload = multer( storage: multerS3( s3: s3,
bucket: 'your- object-storage-here',
acl: 'public-read',
key: function (request, file, cb) console.log(file);
cb(null, file.originalname);
>
>)
>).array('upload', 1);

Функция upload готова, остался последний шаг – соединить форму загрузки с кодом для отправки файла и маршрутизации пользователя. Перейдите в конец файла server.js и вставьте этот код прямо над методом app.listen().

.
app.post('/upload', function (request, response, next) upload(request, response, function (error) if (error) console.log(error);
return response.redirect("/error");
>
console.log('File uploaded successfully.');
response.redirect("/success");
>);
>);

Когда пользователь нажимает кнопку отправки, в /upload отправляется POST запрос. Node прослушивает этот POST и вызывает функцию upload(). Если обнаружена ошибка, условный оператор перенаправляет пользователя на страницу /error. Если запрос обработан успешно, пользователь будет перенаправлен на страницу /success, и файл будет загружен в ваше хранилище объектов.

Полный код файла server.js выглядит так:

// Load dependencies
const aws = require('aws-sdk');
const express = require('express');
const multer = require('multer');
const multerS3 = require('multer-s3');
const app = express();
// Set S3 endpoint to Object Storage
const spacesEndpoint = new aws.Endpoint('nyc3.your-object-storage.com');
const s3 = new aws.S3( endpoint: yourEndpoint
>);
// Change bucket property to your Space name
const upload = multer( storage: multerS3( s3: s3,
bucket: 'your-object-storage-here',
acl: 'public-read',
key: function (request, file, cb) console.log(file);
cb(null, file.originalname);
>
>)
>).array('upload', 1);
// Views in public directory
app.use(express.static('public'));
// Main, error and success views
app.get('/', function (request, response) response.sendFile(__dirname + '/public/index.html');
>);
app.get("/success", function (request, response) response.sendFile(__dirname + '/public/success.html');
>);
app.get("/error", function (request, response) response.sendFile(__dirname + '/public/error.html');
>);
app.post('/upload', function (request, response, next) upload(request, response, function (error) if (error) console.log(error);
return response.redirect("/error");
>
console.log('File uploaded successfully.');
response.redirect("/success");
>);
>);
app.listen(3001, function () console.log('Server listening on port 3001.');
>);

Остановите сервер Node, нажав Control+C, и перезапустите его, чтобы обновить параметры:

Перейдите в корень проекта, выберите файл и отправьте форму. Если все настроено правильно, вы будете перенаправлены на страницу success, и в хранилище объектов появится новый общедоступный файл.

Success!
File uploaded successfully.

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

Заключение

Теперь у вас есть приложение на Node.js и Express для отправки файлов в хранилище объектов.

Получившееся приложение – отличный старт для настройки хранилища объектов. Однако прежде чем запустить приложение в производство, необходимо принять дополнительные меры предосторожности (например, настроить аутентификацию).

На первый взгляд кажется: “Что может быть сложного в загрузке файла на сервер”? Но, оказывается, не всё так просто. Мы настолько привыкли к готовым встроенным в языки иструментам, что перестали понимать как они работают. Давайте немного погрузимся в тему и разберём, как же загрузить файл на сервер и подготовить его к дальнейшей обработке на примере Node.js.

Вопрос первый: Content-Type

Передача файла из HTML-формы: Content-Type: multipart/form-data

Первый способ и наверное самый распространнённый — это передача файла из HTML-формы. Если особо не мудрить с JavaScript на клиенте, то файл, прикреплённый через поле <input type="file"> , отправится на сервер именно таким способом. Представим, что у нас есть следующая форма на странице:

На том месте, где у меня многоточия, на самом деле, очень много всего. Если кому интересно узнать, как на самом деле передаются файлы по сети, можно перехватить уходящие запросы со своего компьютера с помощью программы Wireshark.

Передача голых файлов: Content-Type: image/png

Проще всего показать пересылку таких файлов на примере утилиты cUrl.

Посмотрим что говорит Wireshark:


Видим, что таким методом отправляется только наш файл и ничего более. В большинстве случаев именно это и нужно, чтобы сделать качественный, красивый и удобный интерфейс. Так же можно заметить, что используется метод PUT. Никто, конечно, не мешает поменять руками на POST, но обычно при таком типе передачи используется именно PUT.

Вопрос второй: проверка файла на стороне сервера

Давайте сформируем полный список того, что нужно проверить на сервере, прежде чем вернуть пользователю ответ с кодом 201 Created (файл загружен):

  1. Если Content-Length установлен, то он должен быть меньше установленного лимита. Если это не так, то вернуть код 413 Request Entity Too Large .
  2. Если Content-Type установлен, то он должен быть одним из разрешённых. Если это не так, то вернуть код 422 Unprocessable Entity .
  3. Расширение загружаемого файла, должно быть одним из разрешённых. Если это не так, то вернуть код 422 Unprocessable Entity .
  4. Фактический размер файла должен быть меньше установленного лимита.
  5. Файл должен быть полностью и без ошибок загружен на сервер. Если это не так, то вернуть код 500 Internal Server Error .

На первый взгляд всё просто. Но есть один нюанс: всё было бы просто, если бы использовалась передача с Content-Type: multipart/form-data . Для такого типа загрузки файлов написано бесчисленное множество библиотек для Node.js, а во многих языках забота о загрузке файлов на сервер таким способом и вовсе снята с программиста. Например, в PHP мы просто можем использовать массив $_FILES . Т.е. язык гарантирует, что файл уже есть на сервере и остаётся только с ним работать. В Node.js такого поведения можно добиться с помощью следующих библиотек:

    — отличное решение если вы используете фреймворк Express. — более низкоуровневое решение, чем Multer. Но функционала в нём не меньше. Отлично можно приспособить к любому используемому фреймворку.

Но всё не так радужно, если мы не используем multipart/form-data . В этом случае во многих языках нам самим придётся позаботиться о сохранение файла куда-нибудь на сервер (например в /tmp ). Рассмотрим как это можно сделать на Node.js.

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

Сразу скажу: поток это такой объект, который порождает события (для искушённых — имплементирует EventEmitter ). Нам нужно слушать эти события и как-то на них реагировать. Событие поступления нового чанка называется в Node.js data . Т.е. нам как минимум нужно написать обработчик события data .

К сожалению, люди на просторах интернета чаще предлагают одно в корне неверное решение. (Я конечно нагнетаю. На самом деле это решение жизнеспособно, но влечёт за собой ряд проблем.)

Давайте посмотрим, как делать НЕ НАДО. Привожу пример обработчика события data . В данном примере request — это объект запроса.

Что же здесь не так? А то, что пришедшие чанки сохраняются в переменную, которая, в свою очередь, хранится в оперативной памяти. Это порождает потенциальную уязвимости. Да и вообще: зачем нам лишний раз занимать ОЗУ, когда можно этого не делать?

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

Это всё. Теперь загрузка файлов не будет забивать нам оперативку. Можно запустить сервер и проверить, выполнив в консоле:

Если у вас что-то не работает, удостоверьтесь, что используете свежую версию Node.js. Данный код точно работает на Node.js v7.4.0.

Что нам понадобилось из сторонних библиотек:

    — для проверки Content-Type. — для создания временного файла на диске для сохранения потока.

Что я не осветил в данной статье: Transfer-Encoding: chunked . Это уже на самостоятельное прочтение. Но стоит заметить, что данных сниппет будет работать и с этим заголовком.

Для работы с файлами в Node.js используется встроенный модуль fs , который выполняет все синхронные и асинхронные операции ввода/вывода применительно к файлам. Чтение и запись файла могут осуществляться одним из двумя способов:

  • с использованием Buffer ;
  • через создание соответствующего потока.

Чтение файлов и директорий¶

Для чтения файла в асинхронном режиме используется метод Node.js readFile() , который принимает три параметра:

  • путь к файлу;
  • кодировка;
  • callback-функция, вызываемая после получения содержимого файла.

Callback-функции передается два аргумента: ошибка и полученные данные в строковом формате. Если операция прошла успешна, то в качестве ошибки передается null .

Если в readFile() не указать кодировку, то данные файла будут возвращены в формате Buffer .

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

Node.js readFileSync() возвращает результат чтения файла и принимает два параметра:

Обработка и перехват ошибок при использовании readFileSync() осуществляется с помощью конструкции try<. >catch() <. >.

Чтобы инициировать ошибку, укажите неправильный путь к файлу.

Методы readFile() и readFileSync() для работы с файлами используют Buffer . Но есть и другой способ считать содержимое файла: создать поток с помощью Node.js fs.createReadStream() . Любой поток в Node.js является экземпляром класса EventEmitter , который позволяет обрабатывать возникающие в потоке события.

Параметры, принимаемые fs.createReadStream() :

  • путь к файлу;
  • объект со следующими настройками:
  • encoding - кодировка (по умолчанию utf8 );
  • mode - режим доступа (по умолчанию 0o666 );
  • autoClose - если true , то при событиях error и finish поток закроется автоматически (по умолчанию true ).

Вместо объекта настроек можно передать строку, которая будет задавать кодировку.

Использование потока имеет ряд преимуществ перед Buffer :

Для чтения директорий используются методы readdir() и readdirSync() , для асинхронного и синхронного режимов соответственно.

Node.js readdir() работает асинхронно и принимает три аргумента:

  • путь к директории;
  • кодировку;
  • callback-функцию, которая принимает аргументами ошибку и массив файлов директории (при успешном выполнении операции ошибка передается как null ).

Node.js readdirSync() работает синхронно, возвращает массив найденных файлов и принимает два параметра:

Создание и запись файлов и директорий¶

В Node.js файлы могут быть записаны также синхронно и асинхронно. Для асинхронной записи имеется метод writeFile() , принимающий следующие аргументы:

  • путь к файлу;
  • данные для записи;
  • параметры записи:
  • кодировка (по умолчанию utf8 );
  • права доступа (по умолчанию 0o666 );
  • callback-функция, которая вызывается по завершению операции и единственным аргументом принимает ошибку (в случае успешной записи передается null ).

Если нет необходимости указывать параметры записи, то третьим параметром Node.js writeFile() можно сразу передать callback-функцию.

Для синхронной записи Node.js файла используйте writeFileSync() . Метод принимает все те же аргументы, что и writeFile() за исключением callback-функции. В качестве значения возвращает undefined .

Как и в случае с readFileSync() обработка ошибок происходит с помощью try<. >catch() <. >.

Методы writeFile() и writeFileSync() перезаписывают уже имеющуюся в файле информацию новыми данными. Если вам нужно внести новые данные без удаления старых, используйте методы appendFIle() и appendFileAsync() , которые имеют идентичные параметры.

Для записи файла через потока ввода имеется метод fs.createWriteStream() , который возвращает поток ввода и принимает два параметра:

  • путь к файлу;
  • объект со следующими настройками:
  • encoding - кодировка (по умолчанию utf8 );
  • mode - режим доступа (по умолчанию 0o666 );
  • autoClose - если true , то при событиях error и finish поток закроется автоматически (по умолчанию true ).

Чтобы создать директорию, используйте методы mkdir() и mkdirSync() .

Node.js mkdir() работает асинхронно и принимает в качестве параметров:

  • путь к директории;
  • объект со следующими настройками:
  • recursive - если true , создает директорию и все ее родительские директории согласно указанному пути, если они еще не существуют (по умолчанию false , т. е. все родительские директории уже должны быть созданы, иначе будет сгенерирована ошибка);
  • mode - режим доступа, параметр не поддерживается на ОС Windows (по умолчанию 0o777 );
  • callback-функцию, которая единственным аргументом принимает ошибку, при успешном создании директории передается null .

Вторым параметром можно сразу передать callback-функцию.

Node.js mkdirSync() создает директорию синхронно и возвращает undefined . Обработка ошибок осуществляется через try<. >catch() <. >. Метод mkdirSync() принимает те же параметры, что и mkdir() , за исключением callback-функции.

Удаление файлов и директорий¶

Чтобы удалить в Node.js файлы используйте методы unlink() и unlinkSync() .

Метод unlink() асинхронный и принимает имя файла, который нужно удалить, и callback-функцию с ошибкой в качестве параметра ( null , если удаление прошло успешно).

Для синхронного удаления файла используйте unlinkSync() , которому единственным аргументом передается имя файла.

Для удаления директорий имеются методы rmdir() и rmdirSync() соответственно. Они полностью идентичны unlink() и unlinkSync() , только вместо имени файла принимают имя директории.

Доброго времени суток, друзья. Поговорим сегодня о работе с файлами в Node.js. Для работы с файлами используется модуль fs (сокращение от File System).

В этой статье мы рассмотрим следующие темы:

Для начала работы нам потребуется установленная Node.js. Подробную инструкцию по ее установке вы можете получить (тут).

Прежде чем начать работу с модулем, его следует импортировать в рабочем файле.

Пробежимся по основным методам этого модуля и посмотрим на примерах как с ними можно работать.

Работа с файловыми дескрипторами

Прежде чем двигаться дальше, давайте посмотрим на термины, о которых описано в статье ниже.

Файловый дескриптор — это неотрицательное целое число. Когда создается новый поток ввода-вывода, ядро возвращает процессу, создавшему поток ввода-вывода, его файловый дескриптор (Wikipedia).

Перейдем к примерам.

Ниже я приведу перечень флагов доступа к файлам

Следует помнить, что дескрипторы файлов необходимо закрывать для предотвращения переполнения памяти, а также проблем с производительностью. Выполним данную задачу с помощью метода close() и его синхронного аналога closeSync().

Работа с директориями

Для проверки существующей директории (файла) и доступов к нему в модуле fs применяется метод access

Вторым параметром устанавливается константа режима проверки:

Создание новой папки

Для создания каталогов присутствует асинхронный метод mkdir и синхронный mkdirSync.

Для создания в текущей директории нового каталога, перед путем следует указать переменную __dirname как вариант реализации абсолютного пути, либо воспользоваться метом resolve модуля path.

Чтение содержимого папки

Для получения содержимого директории используются два метода readdir и readdirSync. Первым параметром для методов передается путь директории, содержимое которой нужно получить.

Удаление папки

Удаление директории производится с помощью методов rmdir и rmdirSync. Первым параметром методов является путь удаляемой директории.

Получение системной информации о файле

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

Вся информация хранится в получаемом объекте stats. Данный объект хранит в себе методы для получения дополнительной полезной информации.

Перечислю некоторые из этих свойств:

stats.isDirectory() метод позволяет узнать, является ли файл директорией;

stats.isFile() метод возвращает true, если это файл;

stats.isSocket() метод возвращает true, если это сокет;

stats.isSymbolicLink() метод возвращает true, если файл является символьной ссылкой;

stats.size свойство, которое возвращает размер файла;

stats.birthtime возвращает время и дату, когда данный файл был создан.

Модуль path и путь к файлу Node.js

Основной проблемой при работе с файлами и папками в операционных системах является разный синтаксис написания путей их расположения. Для решения этой проблемы в Node.js есть модуль path c набором полезных методов.

Для началы работы с модулем его нужно импортировать.

Получение имени, пути и расширения файла

Предположим, что в папке /temp лежит файл template.txt. Воспользуемся методами модуля path для получения имени файла, пути к нему, а так же его расширения.

Метод basename возвращает наименование файла. Первым параметром передается путь к файлу, вторым параметром (опционально) передается расширение файла, если необходимо получить наименование файла без расширения.

path.basename(file, ‘.txt’) // tempalate

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

Метод extname возвращает расширение переданного файла.

Работа с путями файла

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

Метод join принимает список параметров, объединяет их в одну строку, используя разделитель, подходящий к конкретной операционной системе, в которой будет исполнятся код.

Метод resolve используется для нахождения абсолютных путей к файлу.

Метод normalize позволяет найти путь к файлу, используя синтаксис переходов (.. и .) по папкам.

Переименование файла или директории

Методы rename() и renameSync() первым параметром принимают путь к файлу, который нужно переименовать. Второй параметр отвечает за новое наименование файла.

Чтение файла

Если вторым параметром не указана кодировка, то возвращается Buffer. Эти методы полностью загружают файлы в память компьютера, что может сильно отразиться на производительности. Если размер файла большой, то стоит воспользоваться потоками fs.createReadStream()

Запись файла

Чтобы перезаписать контент файлов, используются методы writeFile и writeFileSync. Важный момент! Если файла, контент которого нужно перезаписать, не существует, то он будет создан автоматически.

Копирование файла

Методы copyFile() и copyFileSync() первым параметром принимают путь файла для копирования. Второй параметр принимает название пути и нового файла. Третьим параметром является колбэк функция, которая возвращает ошибку.

Удаление файла

Последнее, что мы рассмотрим в этой статье будут методы unlink() и unlinkSync(). Первым параметром методы принимают путь к удаляемому файлу. Второй параметр в методе unlink возвращает колбэк функцию с ошибкой.

Заключение

В данной статье мы разобрали работу Node.js с файлами, на примерах посмотрели основные полезные методы модулей fs и path. Исходный код вы сможете найти тут. Надеюсь данная статья была вам полезна. Учитесь, думайте, пишите код. Удачного кодинга, друзья!

Подписывайтесь на наш канал в Telegram и на YouTube для получения самой последней и актуальной информации.

Как загрузить файл с Node.js без использования сторонних библиотек ?

Мне не нужно ничего особенного. Я хочу только загрузить файл с указанного URL, а затем сохранить его в указанном каталоге.

"скачать файл с помощью node.js" - вы имеете в виду загрузку на сервер? или получить файл с удаленного сервера, используя ваш сервер? или передать файл клиенту для загрузки с вашего сервера node.js? «Я только хочу скачать файл с заданного URL-адреса, а затем сохранить его в заданном каталоге», - кажется, это довольно ясно. :) Джозеф неверно утверждает, что все процессы узлов являются серверными процессами @lededje Что мешает процессу сервера загрузить файл и сохранить его в каталоге на сервере? Это идеально выполнимо.

Если вы хотите поддерживать сбор информации в командной строке - например, указание целевого файла или каталога или URL - проверьте что-то вроде Commander .

Я получил следующий вывод на консоль , когда я запустил этот скрипт: node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ Error: connect ECONNREFUSED at errnoException (net.js:646:11) at Object.afterConnect [as oncomplete] (net.js:637:18) . Закрывает ли этот код файл должным образом после завершения сценария или он потеряет данные? @quantumpotato Посмотрите на ответ, который вы получаете от своего запроса

Не забывайте обрабатывать ошибки! Следующий код основан на ответе Аугусто Романа.

@theGrayFox Поскольку код в этом ответе намного длиннее принятого. :) @Abdul, может быть, было бы хорошо, если бы ты поделился с остальным классом тем, что понял? Есть ли способ увидеть скорость загрузки? Как можно отследить сколько мб / с? Спасибо!

Как сказала Мишель Тилли, но с соответствующим потоком управления:

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

Редактировать: Спасибо @Augusto Roman за указание, что cb должно быть передано file.close , а не вызвано явно.

обратный звонок сбивает меня с толку. если я сейчас призываю download() , как бы я это сделал? Что бы я привел в качестве cb аргумента? У меня есть, download('someURI', '/some/destination', cb) но я не понимаю, что положить в cb @Abdul Вы указываете обратный вызов с помощью функции, только если вам нужно что-то сделать, когда файл был успешно извлечен.

Говоря об обработке ошибок, еще лучше слушать ошибки запросов. Я бы даже подтвердил, проверив код ответа. Здесь это считается успешным только для кода ответа 200, но другие коды могут быть хорошими.

Это будет сделано так:

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

Ответ gfxmonk имеет очень жесткую гонку данных между обратным вызовом и file.close() завершением. file.close() фактически принимает обратный вызов, который вызывается после завершения закрытия. В противном случае немедленное использование файла может завершиться неудачей (очень редко!).

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

он «сохраняет» его в переменной, чтобы он не стал глобальной переменной по умолчанию. @philk Как вы знаете, глобальная переменная создается, если var request = удаляется? Вы правы, нет необходимости сохранять запрос, он все равно не используется. Это ты о чем?

Возможно, файл node.js изменился, но, похоже, есть некоторые проблемы с другими решениями (с использованием узла v8.1.2):

Ниже приведено модифицированное решение (с использованием ES6 и обещаний), которое решает эти проблемы.

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