1. 程式人生 > 實用技巧 >react上傳檔案顯示上傳進度

react上傳檔案顯示上傳進度

Axios 是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中。
在使用react, vue框架的時候, 如果需要監聽檔案上傳可以使用axios裡的onUploadProgress.

react上傳檔案顯示進度 demo

  • 前端 快速安裝react應用
確保有node環境

npx create-react-app my-app //當前資料夾建立my-app檔案
cd my-app //進入目錄
npm install antd  //安裝antd UI元件

npm run start //啟動專案
  • src-> App.js
import React from 'react';
import 
'antd/dist/antd.css'; import { Upload, message, Button, Progress } from 'antd'; import { UploadOutlined } from '@ant-design/icons'; import axios from "axios" axios.defaults.withCredentials = true class App extends React.Component { constructor(props) { super(props) this.state = { fileList: [], uploading:
false, filseSize: 0, baifenbi: 0 } } //檔案上傳改變的時候 configs = { headers: { 'Content-Type': 'multipart/form-data' }, withCredentials: true, onUploadProgress: (progress) => { console.log(progress); let { loaded } = progress let { filseSize } = this.state console.log(loaded, filseSize); let baifenbi
= (loaded / filseSize * 100).toFixed(2) this.setState({ baifenbi }) } } //點選上傳 handleUpload = () => { const { fileList } = this.state; const formData = new FormData(); fileList.forEach(file => { formData.append('files[]', file); }); this.setState({ uploading: true, }); //請求本地服務 axios.post("http://127.0.0.1:5000/upload", formData, this.configs).then(res => { this.setState({ baifenbi: 100, uploading: false, fileList: [] }) }).finally(log => { console.log(log); }) } onchange = (info) => { if (info.file.status !== 'uploading') { this.setState({ filseSize: info.file.size, baifenbi: 0 }) } if (info.file.status === 'done') { message.success(`${info.file.name} file uploaded successfully`); } else if (info.file.status === 'error') { message.error(`${info.file.name} file upload failed.`); } } render() { const { uploading, fileList } = this.state; const props = { onRemove: file => { this.setState(state => { const index = state.fileList.indexOf(file); const newFileList = state.fileList.slice(); newFileList.splice(index, 1); return { fileList: newFileList, }; }); }, beforeUpload: file => { this.setState(state => ({ fileList: [...state.fileList, file], })); return false; }, fileList, }; return ( <div style={{ width: "80%", margin: 'auto', padding: 20 }}> <h2>{this.state.baifenbi + '%'}</h2> <Upload onChange={(e) => { this.onchange(e) }} {...props}> <Button> <UploadOutlined /> Click to Upload </Button> </Upload> <Button type="primary" onClick={this.handleUpload} disabled={fileList.length === 0} loading={uploading} style={{ marginTop: 16 }} > {uploading ? 'Uploading' : 'Start Upload'} </Button> <Progress style={{ marginTop: 20 }} status={this.state.baifenbi !== 0 ? 'success' : ''} percent={this.state.baifenbi}></Progress> </div > ) } } export default App;
  • 後臺 使用express搭載web伺服器
1.先建立資料夾webSever
  cd webSever
  npm -init -y  //建立package.json檔案

2.安裝express 以及檔案上傳需要的包
  npm install express multer ejs

3.建立app.js
  • app.js
var express = require('express');
var app = express();
var path = require('path');
var fs = require('fs')
var multer = require('multer')
//設定跨域訪問
app.all("*", function (req, res, next) {
    //設定允許跨域的域名,*代表允許任意域名跨域
    res.header("Access-Control-Allow-Origin", req.headers.origin || '*');
    // //允許的header型別
    res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
    // //跨域允許的請求方式 
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    // 可以帶cookies
    res.header("Access-Control-Allow-Credentials", true);
    if (req.method == 'OPTIONS') {
        res.sendStatus(200);
    } else {
        next();
    }
})


app.use(express.static(path.join(__dirname, 'public')));
//模板引擎
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.get("/", (req, res, next) => {
    res.render("index")
})
//上傳檔案
app.post('/upload', (req, res, next) => {

    var upload = multer({ dest: 'upload/' }).any();
  
    upload(req, res, err => {
      if (err) {
        console.log(err);
        return
      }
      let file = req.files[0]
      let filname = file.originalname
      var oldPath = file.path
      var newPath = path.join(process.cwd(), "upload/" + new Date().getTime()+filname)
      var src = fs.createReadStream(oldPath);
      var dest = fs.createWriteStream(newPath);
      src.pipe(dest);
      src.on("end", () => {
        let filepath = path.join(process.cwd(), oldPath)
        fs.unlink(filepath, err => {
          if (err) {
            console.log(err);
            return
          }
          res.send("ok")
        })
  
      })
      src.on("error", err => {
        res.end("err")
      })
  
    })
  
  })
  

app.use((req, res) => {
    res.send("404")
})
app.listen(5000)

  前端啟動之後,啟動後臺 node app 即可實現