SpringBoot+vue文件上传下载预览分片上传

news2024/11/17 11:22:13

学习链接

Blob & File

上传文件

前台

  • 整个过程,就是在使用FormData 添加 上File(这个Blob),并且key要和后台的名字对应上
  • 在点击上传按钮开始上传之前,使用了URL.createObjectURL(File)创建blobUrl,给了img标签作图片预览
  • 上传完毕后,将input file的value置为空。若将input file置为空,则此时不能再从input file中获取file了,得等下次再选择图片才能获得file,将它置为空的目的是为了下次选择同样的图片,也能触发input file的change事件

后台

  • 后台仅仅就是用MultipartFile声明接收即可,可以使用@RequestParam注解 或 @RequestPart注解
  • 调用MultipartFile#transferTo保存文件
  • 可以从MultipartFile#getInputStream中获取流,比如上传到OSS。

在这里插入图片描述
前端控制台
在这里插入图片描述
后端控制台
在这里插入图片描述

前端

<template>
    <div>
        选择文件: <input type="file" ref="fileInputRef" @change="selectFile" multiple> <!-- 使用multiple属性,可选择多个文件 -->
        <br/>
        <img v-if="imgUrl" :src="imgUrl" alt="" style="width:54px;height:54px;">
        <el-button v-if="imgUrl" type="primary" @click="uploadFile">上传</el-button>

        <hr/>
    </div>
</template>

<script>
import axiosInstance from '@/utils/request.js'
import axios from 'axios'
export default {
    name: 'File',
    data() {
        return {
            imgUrl:''
        }
    },
    methods: {
        selectFile() {

            let file = this.$refs['fileInputRef'].files[0]
            console.log(file)

            // 上传前, 可以预览该图片
            let blobUrl = URL.createObjectURL(file)
            this.imgUrl = blobUrl

        },
        uploadFile() {

            // 因为可能选择多个文件, 所以这里是个数组
            let file = this.$refs['fileInputRef'].files[0]

            let formData = new FormData()

            formData.append('mfile', file) // 必须和后端的参数名相同。(我们看到了, 其实就是把blob文件给了formData的一个key)
            formData.append("type", 'avatar')

            // 可以有下面2种方式, 来上传文件
            /* axiosInstance
                .post('http://127.0.0.1:8083/file/uploadFile',formData, {headers: {'a':'b'}})
                .then(res => {
                    console.log('响应回来: ',res);
                }) */
            axiosInstance({ // 这种传参方式, 在axios的index.d.ts中可以看到
                url:'http://127.0.0.1:8083/file/uploadFile',
                method:'post',
                data: formData, // 直接将FormData作为data传输
                headers: {
                    'a':'b' // 可携带自定义响应头
                }
            }).then(res => {
                console.log('响应回来: ',res);
            })

            console.log(this.$refs['fileInputRef'].value); // C:\fakepath\cfa86972-07a1-4527-8b8a-1991715ebbfe.png
            // 上传完文件后, 将value置为空, 以避免下次选择同样的图片而不会触发input file的change事件。
            // (注意清空value后,将不能再从input file中获取file,而原先的file仍然能够使用)
            this.$refs['fileInputRef'].value = ''
        }
    }
}
</script>

<style>

</style>

后端代码

@PostMapping("uploadFile")
public Object uploadFile(@RequestPart("mfile")MultipartFile multipartFile,@RequestPart("type") String type) throws IOException {

    System.out.println(multipartFile.getClass());
    System.out.println(type);

    // 源文件名
    String originalFilename = multipartFile.getOriginalFilename();
    // 内容类型
    String contentType = multipartFile.getContentType();
    // 文件是否为空(无内容)
    boolean empty = multipartFile.isEmpty();
    // 文件大小
    long size = multipartFile.getSize();
    // 文件的字节数据
    byte[] bytes = multipartFile.getBytes();
    // 获取文件的字节输入流
    InputStream inputStream = multipartFile.getInputStream();
    // 将文件保存到指定路径下
    multipartFile.transferTo(new File("d:/Projects/practice/test-springboot/src/main/resources/file/" + originalFilename));

    System.out.println(originalFilename);
    System.out.println(contentType);
    System.out.println(empty);
    System.out.println(size);
    System.out.println(bytes.length);

    HashMap<String, Object> data = new HashMap<>();
    data.put("data", "ok");
    return data;
}

下载文件

a标签下载

在这里插入图片描述

前端代码

<template>
    <div>
       <a href="http://127.0.0.1:8083/file/downloadFile?filename=头像a.png">avatar3.png</a>
    </div>
</template>

<script>
import axiosInstance from '@/utils/request.js'
import axios from 'axios'
export default {
    name: 'File',
    data() {
        return {
        }
    },
    methods: {
        
    }
}
</script>

<style>

</style>

后台代码

@GetMapping("downloadFile")
public void downloadFile(@RequestParam("filename") String filename) throws Exception {

    // 告知浏览器这是一个字节流,浏览器处理字节流的默认方式就是下载
    // 意思是未知的应用程序文件,浏览器一般不会自动执行或询问执行。浏览器会像对待,
    // 设置了HTTP头Content-Disposition值为attachment的文件一样来对待这类文件,即浏览器会触发下载行为
    response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
    // ,该响应头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者网页的一部分),还是以附件的形式下载并保存到本地。
    response.setHeader(HttpHeaders.CONTENT_DISPOSITION,"attachment;fileName="+ URLEncoder.encode(filename, "UTF-8"));
    File file = new File("d:/Projects/practice/test-springboot/src/main/resources/file/" + filename);

    ServletOutputStream ros = response.getOutputStream();

    FileInputStream fis = new FileInputStream(file);
    byte[] bytes = new byte[2 * 1024];
    int len = 0;
    while ((len = fis.read(bytes)) != -1) {
        ros.write(bytes, 0, len);
    }

    ros.flush();
    ros.close();

}

动态a标签下载

  • 后台代码仍然用上面a标签下载的代码即可

在这里插入图片描述

前端代码

  • 只需要动态创建a标签,添加到body,然后手动调用js触发a标签的click事件,触发下载
  • 下载完成之后,将a标签移除
  • 整个过程a标签的样式都是display:none
<template>
    <div>
        <el-button type="success" @click="downloadFile">下载文件</el-button>
    </div>
</template>

<script>
import axiosInstance from '@/utils/request.js'
import axios from 'axios'
export default {
    name: 'File',
    data() {
        return {
        }
    },
    methods: {
        downloadFile() {
            let a = document.createElement('a')
            a.href = 'http://127.0.0.1:8083/file/downloadFile?filename=头像a.png'
            document.body.appendChild(a)
            a.style.display = 'none'
            a.click()
            document.body.removeChild(a)
        }
    }
}
</script>

<style>

</style>

axios + 动态a标签

  • 后台代码仍然用上面a标签下载的代码即可

在这里插入图片描述

前端代码

  • 收到后端的响应流 变成前端的 blob对象,然后使用浏览器的api,URL将blob对象创建为blobUrl,然后动态创建a标签,触发a标签点击完成下载
  • 使用/file/previewFile接口也是一样的效果,其实,只要后端往response里写数据,这里来就能用blob拿到
  • 下面的axios不要用封装的,因为要指定responseType:‘blob’,直接去拿数据
<template>
    <div>
        <el-button type="success" @click="downloadFile">下载文件</el-button>
    </div>
</template>

<script>
import axios from 'axios'
export default {
    name: 'File',
    data() {
        return {
        }
    },
    methods: {
        downloadFile() {
            axios({ // 使用原来的axios实例, 不能用封装的, 因为下面要直接拿响应的blob数据
                url:'http://127.0.0.1:8083/file/downloadFile?filename=头像a.png',
                method:'get',
                headers: {
                    'a':'b'
                },
                responseType: 'blob' // 这个可以在axios的index.d.ts中可以找到
            }).then(response=>{
                return response.data
            }).then(blob=>{
                console.log(blob);
                let ablob = new Blob([blob])
                let blobUrl = window.URL.createObjectURL(ablob)
                let tmpLink = document.createElement('a')
                tmpLink.style.display = 'none'
                tmpLink.href = blobUrl
                tmpLink.setAttribute('download','头像b.png')
                document.body.appendChild(tmpLink)
                tmpLink.click()
                document.body.removeChild(tmpLink)
                window.URL.revokeObjectURL(blobUrl)
            })
        }
    }
}
</script>

<style>

</style>

浏览器直接输入

直接在浏览器的地址栏输入,即可下载,同样用上面的地址即可:http://127.0.0.1:8083/file/downloadFile?filename=头像a.png

在这里插入图片描述

预览文件

  • 前端直接一个a标签即可,后端改个响应头即可。
  • 如果需要在页面中预览,则可使用上面提到的方法,获取到流之后,然后创建为blobUrl或dataUrl放入img标签的src属性即可。

在这里插入图片描述

前端代码

<template>
    <div>
        <a href="http://127.0.0.1:8083/file/previewFile?filename=头像a.png">头像a.png</a>
    </div>
</template>

<script>
import axios from 'axios'
export default {
    name: 'File',
    data() {
        return {
        }
    },
    methods: {
        
    }
}
</script>

<style>

</style>

后端代码

设置好响应头即可

@GetMapping("previewFile")
    public void previewFile(@RequestParam("filename") String filename) throws Exception {

    // 可使用ServletContext 通过文件名获取 媒体资源类型
    response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE);
    File file = new File("d:/Projects/practice/test-springboot/src/main/resources/file/" + filename);

    ServletOutputStream ros = response.getOutputStream();

    // 可参考: StreamUtils
    FileInputStream fis = new FileInputStream(file);
    byte[] bytes = new byte[4 * 1024];
    int len = 0;
    while ((len = fis.read(bytes)) != -1) {
        ros.write(bytes, 0, len);
    }

    ros.flush();
    ros.close();

}

分片上传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/486226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL数据库之库表管理

一、常用的数据类型&#xff1a; 类型含义tinyint(n)1个字节&#xff0c;范围(-128~127)smallint(n)2个字节&#xff0c;范围(-32768~32767)mediumint(n)3个字节&#xff0c;范围(-8388608~8388607)int(n)4个字节(32个比特位)&#xff0c;整数型&#xff0c;范围(-2147483648~…

JavaEE - 网络编程

一、网络编程基础 为什么需要网络编程&#xff1f; 用户在浏览器中&#xff0c;打开在线视频网站&#xff0c;如优酷看视频&#xff0c;实质是通过网络&#xff0c;获取到网络上的一个视频资源。 与本地打开视频文件类似&#xff0c;只是视频文件这个资源的来源是网络。 相比本…

KALI入门到高级【第五章】

预计更新第一章 入门 1.1 什么是Kali Linux&#xff1f; 1.2 安装Kali Linux 1.3 Kali Linux桌面环境介绍 1.4 基本命令和工具 第二章 信息收集 1.1 网络扫描 1.2 端口扫描 1.3 漏洞扫描 1.4 社交工程学 第三章 攻击和渗透测试 1.1 密码破解 1.2 暴力破解 1.3 漏洞利用 1.4 特…

模糊PID(模糊规则表)

模糊PID的模糊化相关内容,请参看下面的博客文章: PLC模糊控制模糊PID(梯形图实现+算法分析)_RXXW_Dor的博客-CSDN博客博途PLC的模糊PID控制详细内容请查看下面的博客文章:Matlab仿真+博途PLC模糊PID控制完整SCL源代码参考(带模糊和普通PID切换功能)_博途怎么实现模糊pid_…

后端程序员的前端必备【Vue】 - 05 class与style绑定、表单输入绑定、Vue生命周期

class与style绑定、表单输入绑定、Vue生命周期 1 class与style绑定1.1 绑定class1.2 绑定style1.3 练习 2 表单输入绑定3 Vue生命周期3.1 vue生命周期3.2 组件的生命周期钩子 1 class与style绑定 操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attri…

【操作系统】操作系统内核

图灵机 当系统中有一个CPU的时候 &#xff0c;MR就是它的状态 当系统中有n个CPU的时候&#xff0c;MR1,MR2…MRn 是它的状态 IRQ和NMI是低电平有效信号 NMI不可屏蔽中断 6502的CPU一共40个引脚 eflags寄存器里的 IF 表示 interrupt enable 1表示可以响应中断&#xff0c;0表示…

破解马赛克有多「容易」?

刷短视频时&#xff0c;估计大家都看过下面这类视频&#xff0c;各家营销号争相曝光「一分钟解码苹果笔刷背后内容」的秘密。换汤不换药&#xff0c;自媒体们戏称其为「破解马赛克」&#xff0c;殊不知让多少不明真相的用户建立起了错误的认知&#xff0c;也让苹果笔刷第 10086…

【网络编程】demo版UDP网络服务器实现

文章目录 一、引入二、服务端实现2.1 创建套接字socket2.2 绑定bind2.3 启动服务器2.4 IP的绑定2.5 读取数据recvfrom 三、用户端实现3.1 绑定问题3.2 发送数据sendto 四、源码 一、引入 在上一章【网络编程】socket套接字中我们讲述了TCP/UDP协议&#xff0c;这一篇就是简单实…

保护移动设备免受恶意软件侵害优秀方法

几天前&#xff0c;移动恶意软件攻击增加了500%显然&#xff0c;我们大多数人都不知道不能很好地保护我们的手机下面小编揭秘有效保护移动设备免受恶意软件侵害的最佳方法。 1、使用移动反恶意软件 恶意软件很容易感染智能手机和平板电脑&#xff0c;因此在设备上安装可靠的…

douyin 之xgorgon0404参数

如果我们想要看抖音的数据&#xff0c;在抓包的时候&#xff0c;会发现有一个xgorgon参数,在请求接口的时候&#xff0c;只需要在请求头携带xgorgon参数&#xff0c;就能获得响应后的数据。 目前抖音的xgorgon0404算法已经还原了&#xff0c; 下面是一个请求的demo。代码如下:…

计算机网络可靠传输的三种基本实现机制

可靠传输的means 在数据链路层会给上层网络层提供可靠传输或者不可靠传输&#xff0c;不可靠传输是指检测到传输差错的时候只是丢弃该分组而不进行任何处理&#xff0c;而可靠传输会给发送者一个信号进行重发该分组。 以下给出的三种基本实现机制是提出一些问题&#xff0c;慢…

截图的背景色如何去除?这里介绍一个小工具

屏幕截图&#xff0c;是方便常用的功能。例如从网页或者视频中截图。但是有时候想去除截图中的背景颜色&#xff0c;怎么办&#xff1f;下面这个案例介绍如何去掉截图中的蓝色背景色。 这个小工具就能帮你方便实现。Web端的便捷小工具链接: http://www.artvily.com/renderCase…

深度学习框架发展趋势

深度学习方法的发展是推动深度学习框架进步的最大动力&#xff0c;因此深度学习框架的功能和设计应顺应 算法和模型的发展趋势&#xff1a; 第一&#xff0c;易用性。深度学习领域仍处于快速发展期&#xff0c;参与者和学习者不断增加&#xff0c;新模型大量提出。因 此&#…

深入篇【C++】类与对象:拷贝构造函数详解

深入篇【C】类与对象&#xff1a;拷贝构造函数详解 ①.拷贝构造函数Ⅰ.概念Ⅱ.特征1.重载形式之一2.参数唯一3.形参必须传引用4.编译器的拷贝函数5.典型调用场景 ②.总结&#xff1a; ①.拷贝构造函数 Ⅰ.概念 在创建对象时&#xff0c;能否创建一个与已存在对象一模一样的新…

[架构之路-186]-《软考-系统分析师》-5-数据库系统 - 关系型数据库、操作型数据库、数据集市、数据仓库的区别?

目录 总体架构&#xff1a; 一、数据库 二、关系型数据库 三、SQL与数据库 四、 分布式数据库 五、数据仓库 1. 概述 2. 架构 3、数据仓库的主要特征 3、1 面向主题性 3、2 集成性 3、3 非易失性 3、4 时变性 总体架构&#xff1a; 一、数据库 数据库是“按照数据…

【链表OJ题 1】反转链表

目录 题目来源&#xff1a; 代码实现 1、方法一 1.1分析 2、方法二 2.1 分析 题目来源&#xff1a; 力扣 题目描述&#xff1a; 代码实现 1、方法一 struct ListNode* reverseList(struct ListNode* head) {struct ListNode* prev NULL, * cur head;while (cur){st…

基础IO+文件

基础IO 回顾文件回顾文件操作库函数调用接口写文件-w读文件-r 系统调用打开文件-open写文件-write 文件操作本质文件描述符fd文件描述符的分配规则重定向 FILE缓冲区模拟实现缓冲区总结 理解文件系统磁盘物理结构存储结构逻辑结构 文件系统软硬链接 动静态库动态库和静态库生成…

Kafka上的优化经验

1. 平滑扩容 Motivation kafka扩容⼀台新机器的流程 假如集群有 3 个 broker &#xff0c;⼀共有 4 个 TP &#xff0c;每个 3 副本&#xff0c;均匀分布。现在要扩容⼀台机器&#xff0c; 新 broker 加⼊集群后需要通过⼯具进⾏ TP 的迁移。⼀共迁移 3 个 TP 的副…

JavaScript高级程序设计(第2版)——读书笔记

文章目录 第1章 JavaScript简介第2章 在HTML中使用JavaScript第3章 基本概念第4章 变量、作用域、内存问题第5章 引用类型第6章 面向对象的程序设计第7章 匿名函数第8章 BOM第9章 客户端检测第10章 DOM第11章 DOM2和DOM3第12章 事件第13章 表单脚本第14章 错误处理与调试第15章…

java 的参数传递

一、疑惑引入 首先&#xff0c;我们从一个例子来引出这个问题&#xff1a; public static void main(String[] args) throws IOException {List<String> mockList Lists.newArrayList("a", "b");System.out.println("1: " mockList);L…