React js处理文件上传

react js handling file upload

本文关键字:文件 处理 js React      更新时间:2023-09-26

我是react js的新手。我想用react js异步上传图像假设代码是

var FormBox = React.createClass({
  getInitialState: function () {
    return {
      photo: []
    }
  },
  pressButton: function () {
    var data = new FormData();
    data.append("photo", this.state.photo);
    // is this the correct way to get file data?
  },
  getPhoto: function (e) {
    this.setState({
      photo: e.target.files[0]
    })
  },
  render: function () {
    return (
      <form action='.' enctype="multipart/form-data">
        <input type='file'  onChange={this.getPhoto}/>
        <button onClick={this.pressButton}> Get it </button>
      </form>
    )
  }
})
ReactDOM.render(<FormBox />, document.getElementById('root'))

任何答案将不胜感激!

您可以使用FileReader

var FormBox = React.createClass({
          getInitialState: function () {
            return {
              file: '',
              imagePreviewUrl: ''
            }
          },
          pressButton: function () {
            e.preventDefault();
          // TODO: do something with -> this.state.file
          console.log('handle uploading-', this.state.file);
          },
          getPhoto: function (e) {
            e.preventDefault();
            let reader = new FileReader();
            let file = e.target.files[0];
            reader.onloadend = () => {
              this.setState({
                file: file,
                imagePreviewUrl: reader.result
              });
            }
            reader.readAsDataURL(file);
            
          },
          render: function () {
            let {imagePreviewUrl} = this.state;
            let imagePreview = null;
            if (imagePreviewUrl) {
              imagePreview = (<img src={imagePreviewUrl} />);
            } else {
              imagePreview = (<div className="previewText">Please select an Image for Preview</div>);
            }
            return (
              <div>
              <form action='.' enctype="multipart/form-data">
                <input type='file'  onChange={this.getPhoto}/>
                <button onClick={this.pressButton}> Get it </button>
              </form>
              <div className="imgPreview">
                {imagePreview}
              </div>
              </div>
            )
          }
        })
        
        ReactDOM.render(<FormBox />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="root"></div>

如果您计划使用node和express上传文件,那么您必须创建服务器和客户端。服务器有api,客户端将使用它来上传带有axios的文件。

  • 服务器部分

首先,我们要放入四个包,分别是express, explicit-fileupload,cors和nodemon。运行以下命令安装应用程序:

npm i express express-fileupload cors nodemon

现在在你喜欢的代码编辑器中打开fileupload文件夹,创建一个名为server.js的全新文档。

// server.js
const express = require('express');
const fileUpload = require('express-fileupload');
const cors = require('cors')
const app = express();
// middle ware
app.use(express.static('public')); //to access the files in public folder
app.use(cors()); // it enables all cors requests
app.use(fileUpload());
// file upload api
app.post('/upload', (req, res) => {
    if (!req.files) {
        return res.status(500).send({ msg: "file is not found" })
    }
        // accessing the file
    const myFile = req.files.file;
    //  mv() method places the file inside public directory
    myFile.mv(`${__dirname}/public/${myFile.name}`, function (err) {
        if (err) {
            console.log(err)
            return res.status(500).send({ msg: "Error occured" });
        }
        // returing the response with file path and name
        return res.send({name: myFile.name, path: `/${myFile.name}`});
    });
})
app.listen(4500, () => {
    console.log('server is running at port 4500');
})

使用node server.js启动服务器。

在你最喜欢的代码编辑器上打开react app文件夹,在src文件夹下创建一个名为fileupload.js的新报告。现在上传以下代码:

// fileupload.js
import React, { useRef, useState } from 'react';
import axios from 'axios';
function FileUpload() {
    const [file, setFile] = useState(''); // storing the uploaded file    
    // storing the recived file from backend
    const [data, getFile] = useState({ name: "", path: "" });    
    const [progress, setProgess] = useState(0); // progess bar
    const el = useRef(); // accesing input element
    const handleChange = (e) => {
        setProgess(0)
        const file = e.target.files[0]; // accesing file
        console.log(file);
        setFile(file); // storing file
    }
    const uploadFile = () => {
        const formData = new FormData();        
        formData.append('file', file); // appending 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 />
            {/* displaying received video*/}
            {data.path && <video src={data.path} autoPlay controls />}
            </div>
        </div>
    );
}
export default FileUpload;

现在在App.js文件中导入FileUpload组件。

// App.js
import React from 'react';
import FileUpload from './fileupload';
import './App.css';
function App() {
  return (
    <div className="App">
      <FileUpload />
    </div >
  );
}
export default App;

运行npm start命令启动react应用。

更多:React File Upload Demo

import axios from 'axios';
var FormBox = React.createClass({
  getInitialState: function () {
    return {
      photo: [],
      name : '',
      documents:[]
    }
  },
  pressButton: function () {
    var component = this
    var data = new FormData();
    data.append("photo", component.state.photo, component.state.name);
    var request = axios.post('http://localhost:3000/document', data)
        request.then(function(response){
    // you need to send data from server in response
          if(response.status == 200){
             console.log('saved in db')
             component.state.documents.push(response.data.documents)
             // pushed document data in documents array
           }
        })

  },
  getPhoto: function () {
    var uploadfile = document.getElementById(upload_doc).files[0]
    this.setState({
      photo: uploadfile, name : uploadfile.name
    })
  },
  render: function () {
    var documents = this.state.documents.map((doc)=>{
       return <div>
                <a href={doc.url}>{doc.name}</a>
                <img src={doc.photo} />
              </div>
    })
   // you can show your documents uploaded this way using map function
    return (
      <form action='.' enctype="multipart/form-data">
        <input type='file' id='upload_doc'  onChange={this.getPhoto}/>
        <button onClick={this.pressButton}> Get it </button>
        <span>{documents}</span>
        // this way you can see uploaded documents
      </form>
    )
  }
})
ReactDOM.render(<FormBox />, document.getElementById('root'))
更简单的方法是使用axios节点模块axios-fileupload
npm install --save axios-fileupload
const axiosFileupload = require('axios-fileupload'); 
axiosFileupload(url,file);

你可以使用React Dropzone Uploader,它为你提供了一个显示文件预览(包括图像缩略图)的Dropzone,并为你处理上传。

import 'react-dropzone-uploader/dist/styles.css'
import Dropzone from 'react-dropzone-uploader'
const Uploader = () => {  
  return (
    <Dropzone
      getUploadParams={() => ({ url: 'https://httpbin.org/post' })} // specify upload params and url for your files
      onChangeStatus={({ meta, file }, status) => { console.log(status, meta, file) }}
      onSubmit={(files) => { console.log(files.map(f => f.meta)) }}
      accept="image/*,audio/*,video/*"
    />
  )
}

上传有进度指标,可以取消或重新启动。UI是完全可定制的,并且库没有依赖关系。

完全声明:这个库是我写的

使用以下模块选择图像。
https://www.npmjs.com/package/react-image-uploader

然后可以使用xhr请求将图像上传到服务器。以下是示例代码:

var xhr  = new XMLHttpRequest();
xhr.onload = function (e) {
//your success code goes here
}
var formData = new FormData();
xhr.open("POST", url, true);
formData.append('file', fileData);
xhr.send(formData);

您可以使用whatwg-fetch来发出post请求。在pressButton()函数中进行以下更改-

import 'whatwg-fetch';
//....
pressButton: function (url) {
    var data = new FormData();
    data.append("photo", this.state.photo);
    var options = {
      body: data,
      timeout: 3000 * 60 * 60
    };
    let callOptions = {
      method : 'POST',
      headers : {
        'Content-Type': 'application/json'
      },
      body : JSON.stringify(options.body)
    }
    return fetch(url, callOptions).then(response => response.json());
}

通过使用FormData检索表单中的所有数据,然后获取所有输入值并使用标题为'content-type': 'multipart/form-data'的axios创建post请求,这就是它的工作方式。

const CreateProfile = () => {
    const handleFormSubmit = async (event) => {
        event.preventDefault();
        const form = new FormData(event.currentTarget);
        const data = {
            name: form.get('name'),
            email: form.get('email'),
            phone: form.get('phone'),
            image: form.get('image'),
        }
        const response = await axios.post('https://example.com/api/create/profile',data,{ headers: {
            'content-type': 'multipart/form-data'
        }});
        console.log(response);
    }
    return (
    <div>
        <form onSubmit={(event) => handleFormSubmit(event)} method="post">
            <input type="text" name="name" required />
            <input type="email" name="email" required />
            <input type="tel" name="phone" required />
            <input type="file" accept="image/jpg, image/png, image/webp" name="image" required />
            <button type="submit">Submit</button>
        </form>
    </div>);
}