React, SpringBoot 中的文件上傳


前后端分離有時候需要實現文件的上傳與下載。現使用React與Springboot做一個簡單的文件上傳Demo

搭建一個最簡單的基於springboot的app:myservice,過程不再贅述

創建一個簡單的controller,用於與前台交流:

package com.example.myservice.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/file")
public class FileController {
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String test() {
        return "hello, this file controller";
    }
}

啟動springboot之后,直接在瀏覽器中get一下,看看是否通了

 

 

 表示運行成功。

搭建一個簡單的基於React的app,現在借助我現有的React-Typescript框架進行試驗

import React from "react";

function MainApp(props: any) {
    return <div>hello, world!</div>
}

export default MainApp;

 

簡單的頁面代碼。

 

 

 頁面運行成功。

 

OK,基本的腳手架搭完,現在就看如何實現。

實現文件上傳:

前端考慮使用偽表單進行上傳,上傳文件希望同時上傳一些其他的數據。

理想中的文件結構:

{
    param1: any;
    param2: any;
    ...
    file: File;
}

根據上述結構,編寫上傳組件雛形

function FileUpload(props: any) {
    return <div>
        <input type="file" />
    </div>
}

function MainApp(props: any) {
    return <FileUpload />
}

頁面上面已經可以顯示一個上傳文件的按鈕,並且有文件上傳動作交互了。但是文件路徑暫存於瀏覽器中,並沒有放到后台。

如何獲取到文件數據呢?有人建議使用id與getElementById。既然這里用了React,為何不嘗試使用ref引用組件呢?

function FileUpload(props: any) {
    const inputRef = React.useRef<any>();
    return <div>
        <input ref={inputRef} type="file" />
        {/** 加一個小button測試引用 */}
        <button onClick={function () {
            console.log(inputRef.current)
        }}>log the ref</button>
    </div>
}

function MainApp(props: any) {
    return <FileUpload />
}

點擊后面的button,查看控制台打印的對象:

 

 

 inputref成功到了對象。

下一步的問題就是如何獲取文件。這里上傳一個文件,然后針對ref進行打印操作,試着獲取各種值:

 

 

 可見value存儲了文件路徑,files存儲着文件內容

通過實驗發現,執行inputRef.current.value = "" 可以清空文件列表,也就是直接對element對象的value空字符串賦值可以清空文件

這里驗證一下上面所說的:

import React from "react";

function FileUpload(props: any) {
    return <div>
        <input type="file"
            onChange={function (event: React.ChangeEvent<HTMLInputElement>) {
                console.log(event.target.value);
                console.log(event.target.files);
            }} />
    </div>
}

function MainApp(props: any) {
    return <FileUpload />
}

export default MainApp;

 

 

 結果正確。下面進行文件數據保存的操作

前台代碼:(使用Axios的異步交互框架進行發送數據)

import Axios from "axios";
import React from "react";

function FileUpload(props: any) {

    const inputRef = React.useRef<any>();

    const [uploadData, setUploadData] = React.useState<any>();

    function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
        // 將文件的第一個保存到uploadData中
        // 僅考慮單文件上傳,多文件上傳原理差不多
        if (event.target.files) {
            var newUploadData = new FormData();
            newUploadData.append("fileInfo", "some file's info");
            newUploadData.append("file", event.target.files[0]);
            setUploadData(newUploadData);
        }
    }

    function handleUpload() {
        uploadData && Axios.post("http://localhost:8080/file/upload", uploadData, {
            headers: {
                "Content-Type": "multipart/form-data"
            }
        }).then(function (response: any) {
            console.log(response.data);
        }).catch(function (error: any) {
            console.log(error.response);
        })
    }

    function handleClean() {
        setUploadData(undefined);
        inputRef.current && (inputRef.current.value = "");
    }

    return <div>
        <input ref={inputRef} type="file" onChange={handleChange} />
        <button onClick={handleUpload}>upload</button>
        <button onClick={handleClean}>clean</button>
    </div>
}

function MainApp(props: any) {
    return <FileUpload />
}

export default MainApp;

后台代碼:

簡單的Dto:

package com.example.myservice.dto;

import org.springframework.web.multipart.MultipartFile;

import lombok.Data;

// lombok注解,可以省略寫getter, setter方法的步驟 @Data
public class FileUploadDto { private String fileInfo; private MultipartFile file; }

Controller:

package com.example.myservice.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.myservice.dto.FileUploadDto;

@RestController
@CrossOrigin("*")
@RequestMapping("/file")
public class FileController {
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String test() {
        return "hello, this file controller";
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "multipart/form-data")
    public String upload(FileUploadDto dto) {
        System.out.println("fileInfo: " + dto.getFileInfo());
        System.out.println("fileSize: " + dto.getFile().getSize());
        return "upload successfully!";
    }
}

上傳文件運行截圖:

 

 

后台log:

 

 項目結束。

由於水平有限,文中難免有錯誤遺漏之處,請大家多多指正批評。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM