基于Node的React图片上传组件实现实例代码

让我来介绍一下实现这个React图片上传组件的完整过程和代码示例。

让我来介绍一下实现这个React图片上传组件的完整过程和代码示例。

概述

React是一个流行的JavaScript库,用于开发用户界面。本方案提供了一种基于Node环境使用React实现图片上传的方式。在实现过程中,我们将使用以下技术和库:

  • React:使用React构建用户界面组件
  • React Dropzone:使用React Dropzone库实现文件拖拽和文件上传
  • Node.js:使用Node.js实现服务器接口和上传功能

准备工作

在使用本方案之前,请确保您已经安装了以下工具和库:

  • Node.js v10.x或更高版本
  • npm 或 yarn 包管理器

在准备好了Node.js和npm或yarn之后,我们需要新建一个React项目。可以使用create-react-app CLI实用程序快速创建一个新的React应用程序。只需使用以下命令即可:

npx create-react-app react-image-uploader

这将在当前目录下创建一个名为react-image-uploader的新React项目。

在项目目录中,在前端接口(端口3000)以外,我们还需要在本地开发服务器(端口3001)上运行Node.js后端。 这可以通过安装和运行Express.js服务器程序实现。

首先,在项目目录中打开终端或命令提示符,然后运行以下命令安装Express:

npm install express

当安装完成后,我们可以创建一个名为server.js的Node.js文件。这是我们的服务端代码。

实现方法

接下来,让我们来实现React图片上传组件的代码。在src文件夹下创建一个名为ImageUploader.js的文件。并添加以下代码:

import React, { Component } from 'react';
import Dropzone from 'react-dropzone';

class ImageUploader extends Component {
  state = {
    files: []
  };

  handleDrop = acceptedFiles => {
    this.setState({
      files: acceptedFiles
    });
  };

  handleSubmit = event => {
    event.preventDefault();
    const formData = new FormData();
    formData.append('file', this.state.files[0]);
    fetch('http://localhost:3001/api/upload', {
      method: 'POST',
      body: formData
    })
      .then(response => response.json())
      .then(data => {
        console.log(data);
      })
      .catch(error => {
        console.error(error);
      });
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <Dropzone onDrop={this.handleDrop}>
          {({ getRootProps, getInputProps }) => (
            <div {...getRootProps()}>
              <input {...getInputProps()} />
              <p>Drag and drop a file here, or click to select a file</p>
            </div>
          )}
        </Dropzone>

        {this.state.files.length > 0 && (
          <div>
            <h5>Selected file:</h5>
            <ul>
              {this.state.files.map(file => (
                <li key={file.name}>
                  {file.name} - {file.size} bytes
                </li>
              ))}
            </ul>
            <button>Upload</button>
          </div>
        )}
      </form>
    );
  }
}

export default ImageUploader;

在这段代码中,我们首先导入 React 和这个文件需要依赖的其他库。在组件的构造函数中,我们将状态初始化为空文件数组。我们定义了handleDrop方法,该方法监听文件拖放事件并将文件添加到组件的状态中。

handleSubmit方法将文件上传到服务器。在该方法中,我们首先使用FormData API创建一个新的FormData对象。然后,我们将当前选定的文件添加到FormData中,为这个对象起一个名为“file”的字段。接下来,我们使用Fetch API发送POST请求到服务器程序,在该请求中,我们将FormData对象作为请求体提交给服务器。最后,我们解析服务器响应,将其打印到控制台中。

render方法中,我们在Dropzone组件中显示拖放区域和上传按钮。一旦用户选择了一个或多个文件并将它们拖到区域内,handleDrop方法将调用并更新组件的状态。当有上传文件时,我们会在页面上显示选定的文件的名称和大小,以及一个Upload按钮。在单击该按钮时,将调用handleSubmit方法并将文件上传到服务器。

接下来我们创建后端服务。在项目根目录下创建一个名为server.js的文件。并添加以下代码:

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
const PORT = 3001;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());

app.post('/api/upload', (req, res) => {
  const file = req.files.file;
  file.mv(`${__dirname}/public/images/${file.name}`, err => {
    if (err) {
      console.error(err);
      return res.status(500).send(err);
    }

    res.json({ fileName: file.name, filePath: `/images/${file.name}` });
  });
});

app.listen(PORT, () =>
  console.log(`Server running at: http://localhost:${PORT}`)
);

在该server.js文件中,我们首先导入了Express.js、body-parser、cors和其他相关库。然后,我们创建一个Express应用程序,并在端口3001上启动服务器。

我们使用app.post()方法,为上传文件的POST请求定义了路由。该路由检索从客户端发送的文件(客户端会以FormData对象的方式发送请求)。通过使用req.files.file属性,我们获取客户端请求中的上传文件。在这里,req.files.filefile是前端上传时的文件名, 但是该属性需要依赖于中间件的支持。对于本文示例,我们使用了express-fileupload中间件,它将请求体中的文件解析为req.files属性。为了简化本文示例,我们不再对详细使用该中间件提供说明。

最后,我们将上传的文件存储到public/images文件夹下,并向客户端发送JSON响应,携带上传文件的名称和路径。该路径可以用于在客户端预览已上传的图像。

示例

为了更好地理解该方案,以下是两个使用示例:

示例一:上传单个图片

先启动 Node 服务,打开终端,进入 server 文件夹, 在本机运行文件 server.js, 作为 node web 服务器。

切换到 react-image-uploader 项目根目录,启动 React 服务,运行以下命令:

npm start

运行完成后,打开浏览器,访问 http://localhost:3000/。在该网页中,你会看到一个文件上传控件。将需要上传的图片拖动到文件上传控件区域,或者点击添加文件按钮弹出对话框选择需要上传的图片后点击上传。

上传成功后,页面会显示上传的文件名及大小,并有一个预览链接;

示例二:上传多个文件

再次启动 React 和 Node 服务器,进入 react-image-uploader 项目根目录,打开 ImageUploader.js 文件:

import React, { Component } from 'react';
import Dropzone from 'react-dropzone';

class ImageUploader extends Component {
  state = {
    files: []
  };

  handleDrop = acceptedFiles => {
    this.setState({
      files: acceptedFiles
    });
  };

  handleSubmit = event => {
    event.preventDefault();
    const formData = new FormData();
    this.state.files.forEach((file, i) => {
      formData.append('file' + i, file);
    });
    fetch('http://localhost:3001/api/upload', {
      method: 'POST',
      body: formData
    })
      .then(response => response.json())
      .then(data => {
        console.log(data);
      })
      .catch(error => {
        console.error(error);
      });
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <Dropzone onDrop={this.handleDrop}>
          {({ getRootProps, getInputProps }) => (
            <div {...getRootProps()}>
              <input {...getInputProps()} />
              <p>Drag and drop some files here, or click to select files</p>
            </div>
          )}
        </Dropzone>

        {this.state.files.length > 0 && (
          <div>
            <h5>Selected files:</h5>
            <ul>
              {this.state.files.map(file => (
                <li key={file.name}>
                  {file.name} - {file.size} bytes
                </li>
              ))}
            </ul>
            <button>Upload</button>
          </div>
        )}
      </form>
    );
  }
}

export default ImageUploader;

说明:在代码示例2中,在ImageUploader组件的handleSubmit方法中,我们使用了forEach方法来迭代所有被选中的文件,然后将它们添加到FormData中,每个文件添加的字段名都不相同,这里存在随机的情况;当上传多个文件时,客户端会向服务器端发送一个包含所有文件的FormData对象,服务器端需要对所有文件进行并发处理,并将它们保存在本地磁盘上。

运行该示例后,资源管理器中存储上传文件的文件夹中会出现多个文件。

结论

在本方案中,我们使用了React Dropzone和fetch API上传图片,同时也使用了Node.js作为后端框架,以实现在本地实现文件上传的功能。你也可以尝试在其他Web框架中使用类似的技术。

祝成功!

本文标题为:基于Node的React图片上传组件实现实例代码

基础教程推荐