Как загружать файлы в React с помощью NodeJS и Express

год назад·3 мин. на чтение

В этой статье рассмотрим как загрузить файлы в React использованием Express в качестве бэкенда.

Создание бэкенда на Express

Во-первых, мы создаем POST API с использованием NodeJS и Express, который поможет нам загружать файлы (изображения, pdf и т. д.) на внутренний сервер.

Настройка серверного проекта

Давайте настроим бэкенд проект NodeJS, выполнив следующие команды одну за другой.
mkdir fileupload
cd fileupload
npm init -y

Установка пакетов

Теперь нам нужно установить четыре пакета: express, express-fileupload, cors и nodemon. Выполните приведенную ниже команду, чтобы установить пакеты.
npm i express express-fileupload cors nodemon
Теперь откройте папку fileupload в вашем любимом редакторе кода и создайте новый файл с именем server.js. Добавьте следующий код в файл server.js.
// server.js

const express = require('express');
const fileUpload = require('express-fileupload');
const cors = require('cors')

const app = express();

// middleware
app.use(express.static('public')); // для доступа к файлам в папке public
app.use(cors());
app.use(fileUpload());

// API для загрузки файлов
app.post('/upload', (req, res) => {
  if (!req.files) {
    return res.status(500).send({ msg: "file is not found" })
  }
   
  const myFile = req.files.file;
 
  // метод mv() помещает файл в папку public
  myFile.mv(`${__dirname}/public/${myFile.name}`,
    function (err) {
      if (err) {
        console.log(err)
        return res.status(500).send({ msg: "Error occurred" });
      }
      // возвращаем ответ с именем файла и его расположением
      return res.send({name: myFile.name, path: `/${myFile.name}`});
  });
})


app.listen(4500, () => {
  console.log('server is running at port 4500');
})
В приведенном выше коде мы сначала импортировали три пакета: express, express-fileupload и cors, а затем создали приложение express вызвав функцию express() Наш маршрут POST API - /upload. Мы помещаем файлы в общую папку public. Для этого нам нужно создать папку public внутри нашего бэкенд-проекта.

Добавление скриптов

Чтобы запускать и перезапускать сервер мы используем nodemon. Откройте файл package.json и добавьте следующий код в scripts.
 "server": "nodemon server.js"
Теперь запустите сервер, выполнив команду npm run server в терминале.

Создание приложения React

Давайте создадим новое React приложение, выполнив следующую команду.
npx create-react-app react-fileupload
Теперь измените текущий рабочий каталог, выполнив приведенную ниже команду.
cd react-fileupload

Установка библиотеки Axios

Нам также необходимо установить клиентскую библиотеку axios, которая используется для выполнения http-запросов.
npm i axios

Создание компонента загрузки файлов

Откройте папку react-fileupload в своем любимом редакторе кода и создайте новый файл с именем fileupload.js внутри папки src. Теперь добавьте следующий код.
// fileupload.js

import React, { useRef, useState } from 'react';
import axios from 'axios';

function FileUpload() {

  // для хранения загруженного файла
  const [file, setFile] = useState('');
  
  // для хранения ответа от бекенда
  const [data, getFile] = useState({ name: "", path: "" });

  const [progress, setProgess] = useState(0); // progessbar
  const el = useRef(); // для доступа к инпуту

  const handleChange = (e) => {
    setProgess(0)
    const file = e.target.files[0]; // доступ к файлу
    console.log(file);
    setFile(file); // сохранение файла
  }

  const uploadFile = () => {
    const formData = new FormData();
    formData.append('file', file); // добавление файла
    axios.post('http://localhost:4500/upload', formData, {
      onUploadProgress: (ProgressEvent) => {
        let progress = Math.round(
          ProgressEvent.loaded / ProgressEvent.total * 100
        ) + '%';
        setProgess(progress);
      }
    }).then(res => {
      console.log(res);
      getFile({
        name: res.data.name,
        path: 'http://localhost:4500' + res.data.path
      })
    }).catch(err => console.log(err))
  }

  return (
    <div>
      <div className="file-upload">
        <input type="file" ref={el} onChange={handleChange} />
        <div className="progessBar" style={{ width: progress }}>
          {progress}
        </div>
        <button onClick={uploadFile} className="upbutton">
          Upload
        </button>
        <hr />
        {/* для показа полученного изображения */}
        {data.path && <img src={data.path} alt={data.name} />}
      </div>
    </div>
  );
}

export default FileUpload;
В приведенном выше коде мы использовали хуки react для управления состоянием, и у нас есть две функции: handleChange и uploadFile. handleChange вызывается после того, как пользователь выбрал файл. Функция uploadFile() используется для загрузки файла в наш /upload api. Существует также индикатор выполнения, который показывает прогресс загрузки файла на сервер, а также мы отображаем изображение после получения ответа от сервера.

Добавление стилей css

Добавьте следующие стили в файл App.css.
.App {
    margin: 2rem auto;
    max-width: 800px;
}

img {
  width: 500px;
  height: 500px;
  object-fit: contain;
}

.progessBar {
  height: 1rem;
  width: 0%;
  background-color: rgb(68, 212, 231);
  color: white;
  padding:2px
}

.file-upload {
  box-shadow: 2px 2px 2px 2px #ccc;
  padding: 2rem;
  display: flex;
  flex-direction: column;

  justify-content: space-between;
  font-size: 1rem;
}

input , div , button{
  margin-top: 2rem;
}

.upbutton {
   width: 5rem;
   padding: .5rem;
   background-color: #2767e9;
   color: aliceblue;
   font-size: 1rem;
   cursor: pointer;
}
Теперь импортируйте компонент FileUpload в файл App.js.
// App.js

import React from 'react';
import FileUpload from './fileupload';
import './App.css';

function App() {
  return (
    <div className="App">
      <FileUpload />
    </div >
  );
}

export default App;
Запустите приложение React, запустив npm start.

Как запустить бэкэнд на Node JS

2 года назад·3 мин. на чтение

В этой статье напишем простой бэкэнд на NodeJS. Этот сервер будет полезен для разработки веб-приложений.

Необходимые условия

Перед созданием бэкэнда на node js нужно, чтобы были установлены все необходимые библиотеки, IDE и ПО, а именно:
  • NodeJS и npm. Их можно скачать с официального сайта nodejs.org. npm установится автоматически вместе с NodeJS.
  • Предпочитаемый IDE, например, Visual Studio Code.
  • Опционально, установить git для удобной работы с кодом.

О приложении

В этой статье напишем небольшой REST API сервер, который будет отдавать список дел по GET запросу. Структура папок будет выглядеть следующим образом.
my-app/

Создание бэкэнда на NodeJS

Запустим команду в папке my-app/ для инициализации проекта:
npm init -y
Эта команда создаст файл package.json. Ключ -y заполнит все поля в package.json значениями по умолчанию. Файл package.json содержит информацию о проекте - название, версия, описание, список зависимостей, скрипты для запуска, сборки и тестирования. Все поля можно будет изменить и вручную после его создания. После инициализации package.json будет выглядеть следующим образом.
{
  "name": "my-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Для создания сервера будем использовать express. Установим его с помощью команды:
npm install express
Создадим файл index.js. В нем будет находится код для запуска сервера. Если порт не задан в переменных среды, то будет использован порт 3010.
// my-app/index.js

const express = require('express');
 
const PORT = process.env.PORT || 3010;
const app = express();
 
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  next();
});
 
app.listen(PORT, () => {
  console.log(`Server listening on ${PORT}`);
});

Запуск сервера

В поле scripts файла my-app/package.json добавим команду для запуска сервера. В результате сможем запускать наш сервер с помощью команды npm start.
...
"scripts": {
  "start": "node ./index.js"
},
...
Из папки my-app/ запустим команду npm start. Если ошибок нет, получим сообщение, что сервер прослушивает порт 3010.
PS C:\tutorials-coding\nodejs-backend\my-app> npm start

> my-app@1.0.0 start
> node ./index.js

Server listening on 3010

Создание API

API это интерфейс, с помощью которого приложение будет общаться с веб-сервером, т.е. запрашивать, изменять или удалять данные. Мы сможем получать эти данные, например, в веб-приложении на React. О том как, делать API запросы к серверу из React приложения, можно прочитать в этой статье. В нашем случае мы создадим API для получения списка дел в формате JSON. Создадим файл /my-app/todo-items.json c объектами todo. Этот массив будем отдавать по запросу /api/todo-items.
[
  {
    "id": 1,
    "text": "Изучить Node JS",
    "done": true
  },
 {
    "id": 2,
    "text": "Изучить JavaScript",
    "done": true
  },
  {
    "id": 3,
    "text": "Изучить React JS",
    "done": true
  },
  {
    "id": 4,
    "text": "Написать приложение",
    "done": false
  }
]
Далее добавим код для создания эндпоинта /api/todo-items. Веб-приложение сможет отправлять на него GET запрос.
// my-app/index.js

// ...

const todoItems = require('./todo-items.json');
app.get('/api/todo-items', (req, res) => {
 res.json({ data: todoItems });
});

app.listen(PORT, () => {
 console.log(`Server listening on ${PORT}`);
});
Для того чтобы изменения применились нужно перезапустить NodeJS сервер. Для остановки скрипта в терминале, в котором запущен npm start, нужно нажать Ctrl + C (Command + C). Далее снова запускаем npm start. Для проверки эндпоинта, вставим в адресную строку браузера http://localhost:3010/api/todo-items. В результате получим такой ответ. Ответ от Node JS сервера

Отправка HTTP запроса к серверу

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

Автоматический перезапуск сервера после обновления кода

Ранее для того чтобы изменения исходного кода сервера вступили в силу, мы перезапускали сервер. Можно ускорить процесс разработки и автоматизировать эту часть с помощью инструмента nodemon. nodemon будет следить за файлами в каталоге, в котором был запущен nodemon, и если какие-либо файлы изменятся, он автоматически перезапустит ваше node js приложение. Установим nodemon как зависимость для разработки.
npm install --save-dev nodemon
Добавим новый скрипт dev в my-app/package.json.
...
"scripts": {
  "dev": "nodemon ./index.js"
},
...
Далее запустим сервер следующим образом.
npm run dev
Теперь, после изменений в коде, увидим, что сервер перезапускается сам. Исходный код