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