首页 前端知识 【一文学会文件上传】SpringBoot JQuery-ajax实现文件上传

【一文学会文件上传】SpringBoot JQuery-ajax实现文件上传

2024-05-07 13:05:51 前端知识 前端哥 833 708 我要收藏
唠嗑部分

上篇文章我们说了使用form表单的input文件域上传文件,上篇文章:

但是现在随着前后端分离的开发方式,这种方式越来越少见了,对于后端工程师来说,接口层并没有多大变化,对于前端工程师、亦或者是干全栈的同学们来说,ajax已经不再陌生,那我们本节就来说说,ajax实现文件上传及文件预览

首先来说FormData与FileReader的使用,都是HTML5新增的API

FormData

FormData 接口提供了一种表示表单数据的键值对 key/value 的构造方式,并且可以轻松的将数据通过XMLHttpRequest.send()方法发送出去,如果发送请求时的编码类型被设为 "multipart/form-data",它会使用和表单一样的格式。

构造函数

// 参数传form表单对象,要求表单中的每一项均有name字段,否则无法帮你做收集
var fd = new FormData(form)

常用api

fd.append(key,value);   // 如果指定的key不存在则会新增一条数据,如果key存在,则追加到数据末尾
fd.set(key,value);      // 如果指定的key存在则会覆盖
fd.get(key);      // 返回该key的第一个值
fd.getAll(key);   // 返回该key的所有值,数组格式
fd.delete(key);   // 删除一项
fd.has(key);     // 判断key是否存在,返回布尔值

FileReader

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件内容,使用 FileBlob 对象指定要读取的文件或数据。

构造函数

const fr = new FileReader(); 

常用api

fr.readAsDataURL(file);   // 参数是一个文件,将文件读取为一个Base64编码的字符串,通过fr.result获取
fr.onload = () => {};     // 事件,读取过程是异步的,读取完会执行
言归正传

1、创建项目&导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.4.2</version>
        <relativePath/>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cxs</groupId>
    <artifactId>ajax-file-upload</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

2、编写前端页面结构

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajax-文件上传</title>
    <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
</head>
<body>
    <div>
        <form id="form">
            用户名:<input type="text" name="username"/><br/>
            密码: <input name="password" type="password"/><br/>
            <input id="file" type="file" name="file" style="display: none;"/>
            <label for="file">
                <img id="img" src="" title="+" width="300" height="150" style="cursor: pointer;"/>
            </label>
            <button>上传</button>
        </form>
    </div>
</body>
</html>

3、后端接口部分

@PostMapping("/upload")
public Map<String, Object> upload(User user, @RequestParam("file") MultipartFile file){
    Map<String, Object> result = new HashMap<>();
    result.put("code", 200);
    try {
        if (!ObjectUtils.isEmpty(file)) {
            // 获取源文件的名字
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.hasLength(originalFilename)) {
                // 进行文件上传
                String fullPath = PATH + File.separator + originalFilename;
                File f = new File(fullPath);
                if (!f.exists()) {
                    f.createNewFile();
                }
                file.transferTo(f);
                user.setAvatar(fullPath);
                result.put("data", fullPath);
                result.put("user", user.toString());
            }
        } else {
            result.put("code", 400);
            result.put("msg", "文件不能为空!");
        }
    } catch (IOException e) {
        e.printStackTrace();
        result.put("code", 500);
        result.put("msg", "文件上传失败!");
    }
    return result;
}

4、文件预览-FileReader的使用

详解请看注释

// 给input框添加change事件,监听文件的改变
inp.addEventListener("change",function(){
    // 获取到文件,inp.files是一个集合
    const file = inp.files[0];
    // 基础校验
    if(!file) {
        // 点击了取消,将预览置空
        img.src = currentPath;
        // 清空currentFile
        currentFile = undefined;
        return;
    }
    // 文件格式判断,这里只能传图片
    if(!file.type.startsWith("image")) return window.alert('请选择图片');
    // 给currentFile赋值
    currentFile = file;
    // 读取文件,进行预览
    const fr = new FileReader();
    // 将文件读取为一个base64编码
    fr.readAsDataURL(file);
    // fr读取是一个异步操作,读取完会执行下面函数
    fr.onload = () => {
        console.log(fr.result)
        img.src = fr.result;
    }
})

5、文件上传-FormData的使用

Jquery对于ajax的处理说明:

jQuery帮我们做了封装,会将所有请求的请求头设置为application/x-www-form-urlencoded,而文件上传要求是multipart/form-data

此时如果按照jQuery默认的就会出现问题

解决:不让jQuery帮我们设置就可以:contentType:false,告诉jQuery不要设置我请求头里的content-type

jQuery还会帮我们把数据格式转化为key=value的形式

解决:不让jQuery自动格式化数据:processData:false,告诉jQuery别帮我格式化数据

// 表单的提交事件
$("#form").submit(function (e){
    // 阻止表单submit事件的默认行为,否则会有个刷新的现象
    e.preventDefault()
    // 创建formdata,FormData会将form表单中带有name的字段自动处理成每一项
    var formData = new FormData(this);
    if(!currentFile) return window.alert("请选择文件再上传");
    // 发送ajav请求上传
    $.ajax({
        // 服务器接口地址
        url: '/upload',
        // 请求方式
        type: 'post',
        // 参数
        data: formData,
        // 这两个参数在文件上传时较特殊,详细请看文章描述
        contentType : false,
        processData : false,
        // 成功的回调函数
        success : (resp) => {
            console.log(resp)
        }
    })
})
测试&结语

测试如下图

image-20230307113011711

结语

1、本文采用jQuery作为ajax库,axios大家可自行研究(类似)

2、源码获取方式,全栈小白公众号后台回复:文件上传

转载请注明出处或者链接地址:https://www.qianduange.cn//article/7349.html
标签
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!