1. 上传功能模块

1.1 上传概述

文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。

文件上传时,对页面的form表单有如下要求:

表单属性 取值 说明
method post 必须选择post方式提交
enctype multipart/form-data 采用multipart格式上传文件
type file 使用input的file控件上传

1.2 前端介绍

1). 简单html页面表单

<form method="post" action="/common/upload" enctype="multipart/form-data"><input name="myFile" type="file"  /><input type="submit" value="提交" />
</form>

2). ElementUI中提供的upload上传组件

目前一些前端组件库也提供了相应的上传组件,但是底层原理还是基于form表单的文件上传。

1.3 服务端介绍

服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件:

  • commons-fileupload

  • commons-io

而Spring框架在spring-web包中对文件上传进行了封装简化代码,只需要在Controller的方法中声明一个MultipartFile类型的参数即可接收上传的文件。

1.4 下载介绍

文件下载,也称为download,是指将文件从服务器传输到本地计算机的过程。通过浏览器进行文件下载,通常有两种表现形式:

1). 以附件形式下载,弹出保存对话框,将文件保存到指定磁盘目录

2). 直接在浏览器中打开

通过浏览器进行文件下载,本质上就是服务端将文件以流的形式写回浏览器的过程。

1.5 上传功能模块逻辑分析

1.3.1 前端代码分析

对于前端页面文件上传,可以使用ElementUI提供的上传组件,将其拷贝到项目的目录(resources/backend/page/demo)下,启动项目,访问上传页面。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传</title><!-- 引入样式 --><link rel="stylesheet" href="../../plugins/element-ui/index.css" /><link rel="stylesheet" href="../../styles/common.css" /><link rel="stylesheet" href="../../styles/page.css" />
</head>
<body><div class="addBrand-container" id="food-add-app"><div class="container"><el-upload class="avatar-uploader"action="/common/upload":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeUpload"ref="upload"><img v-if="imageUrl" :src="data:imageUrl" class="avatar"></img><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></div></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="../../plugins/vue/vue.js"></script><!-- 引入组件库 --><script src="../../plugins/element-ui/index.js"></script><!-- 引入axios --><script src="../../plugins/axios/axios.min.js"></script><script src="../../js/index.js"></script><script>new Vue({el: '#food-add-app',data() {return {imageUrl: ''}},methods: {handleAvatarSuccess (response, file, fileList) {this.imageUrl = `/common/download?name=${response.data}`},beforeUpload (file) {if(file){const suffix = file.name.split('.')[1]const size = file.size / 1024 / 1024 < 2if(['png','jpeg','jpg'].indexOf(suffix) < 0){this.$message.error('上传图片只支持 png、jpeg、jpg 格式!')this.$refs.upload.clearFiles()return false}if(!size){this.$message.error('上传文件大小不能超过 2MB!')return false}return file}}}})</script>
</body>
</html>

​http://localhost:8080/backend/page/demo/upload.html​

页面效果如下:

在上述的浏览器抓取的网络请求中,上传文件的调用url,在哪里配置的呢,这个时候,我们需要去看一下前端上传组件。

虽然上述是ElementUI封装的代码,但是实际上最终还通过file域上传文件,如果未指定上传文件的参数名,默认为file。

1.6 上传服务端代码逻辑

# 编写文件上传的方法, 通过MultipartFile类型的参数即可接收上传的文件, 方法形参的名称需要与页面的file域的name属性一致。

1). 获取文件的原始文件名, 通过原始文件名获取文件后缀

2). 通过UUID重新声明文件名, 文件名称重复造成文件覆盖

3). 创建文件存放目录

4). 将上传的临时文件转存到指定位置

2 下载功能模块

2.1 前端代码

文件下载,前端页面可以使用<img>标签展示下载的图片。

<img v-if="imageUrl" :src="data:imageUrl" class="avatar"></img>

解析通过<img>标签如何展示图片数据具体的流程:

在文件上传成功后,在 handleAvatarSuccess 方法中获取文件上传成功之后返回的数据(文件名),然后调用 /common/download?name=xxx 进行文件的下载。在这里,如果想让上传的照片能够在页面展示出来,所以需要在服务端将文件以流的形式写回浏览器。

2.2 下载功能模块逻辑分析

# 在 CommonController 中定义方法download,并接收页面传递的参数name,然后读取图片文件的数据,然后以流的形式写回浏览器。

1). 定义输入流,通过输入流读取文件内容

2). 通过response对象,获取到输出流

3). 通过response对象设置响应数据格式(image/jpeg)

4). 通过输入流读取文件数据,然后通过上述的输出流写回浏览器

5). 关闭资源

3 上传与下载服务端代码实现

1). application.yml (需要在application.yml中定义文件存储路径 )

server:# 端口设计port: 8080
spring:application:# 应用名称(可选)name: reggie_take_outdatasource:# 数据集druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: 123456
mybatis-plus:configuration:#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:# ID生成策略:ASSIGN_ID:可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键id-type: ASSIGN_IDreggie: # 需要在application.yml中定义文件存储路径path: D:\Java-Pro\reggie_take_out\file\

2). CommonController

代码实现:

package com.itheima.reggie.controller;import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.UUID;/*** Description: 文件的上传和下载* @date 2022/8/17 9:55*/@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {@Value("${reggie.path}")private String basePath;@PostMapping("upload")public R<String> upload(MultipartFile file){ // 这个名字必须和前端页面的name一样/**@Description: 文件上传* @version v1.0* @author LiBiGo* @date 2022/8/17 10:31*/// file 是一个临时文件 需要转存,不然运行结束自动删除log.info(file.toString());// 原始文件名String originalFilename = file.getOriginalFilename();// 获得原文件后缀String suffix =originalFilename.substring(originalFilename.lastIndexOf("."));// 使用UUID重新生成文件名,防止文件名称重复String fileName = UUID.randomUUID().toString() + suffix;// 创建目录对象File dir = new File(basePath);// 判断当前目录是否存在if(!dir.exists()){// 目录不存在,需要创建dir.mkdir();}try {file.transferTo(new File(basePath+fileName));} catch (IOException e){e.printStackTrace();}return R.success(fileName);}@GetMapping("/download")public void download(String name , HttpServletResponse response){/**@Description: 文件下载* @version v1.0* @author LiBiGo* @date 2022/8/17 10:31*/try {//输入流,通过输入流读取文件内容FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));//输出流,通过输出流将文件写回浏览器ServletOutputStream outputStream = response.getOutputStream();response.setContentType("image/jpeg"); // 设置响应的文件格式,也可以不设置int len = 0;byte[] bytes = new byte[1024];while ((len = fileInputStream.read(bytes)) != -1){outputStream.write(bytes,0,len);outputStream.flush();}//关闭资源outputStream.close();fileInputStream.close();} catch (Exception e) {e.printStackTrace();}}
}

基于Springboot外卖系统13:实现文件上传下载模块相关推荐

  1. 基于华为云obs的springMVC文件上传下载,简单demo

    使用华为云的obs作为文件服务 使用springdata jpa框架操作数据库 创建springboot项目,添加华为云obs的SDK的maven依赖 <!-- 开启spring配置类 --&g ...

  2. 瑞吉外卖 04 CRUD 菜品 + 文件上传下载

    文件上传下载 预准备 前端代码: 会动态生成一个图像元素. 代码实现 文件上传 在resource/backend/page下创建demo文件,将资料/文件上传下载页面中upload.html复制到这 ...

  3. SB_5_瑞吉外卖_4_文件上传下载_菜品新增_菜品分页查询_菜品修改

    瑞吉外卖-Day04 课程内容 文件上传下载 菜品新增 菜品分页查询 菜品修改 1. 文件上传下载 1.1 上传介绍 1.1.1 概述 文件上传,也称为upload,是指将本地图片.视频.音频等文件上 ...

  4. 基于华为云obs实现文件上传下载(技术栈mysql+springboot+Maven+jsp+java)的技术分享

    基于华为云obs实现文件上传下载(技术栈mysql+springboot+jsp+java)的技术分享 obs实现文件上传下载 前言 一.OBS是什么? 二.使用步骤 1.1 前期准备 2 工具的内容 ...

  5. SpringBoot整合阿里云OSS文件上传、下载、查看、删除

    SpringBoot整合阿里云OSS文件上传.下载.查看.删除 该项目源码地址:https://github.com/ggb2312/springboot-integration-examples ( ...

  6. 项目_功能模块_基于Spring Boot的文件上传下载功能的设计与实现

    文章目录 基于Spring Boot的文件上传下载功能模块的设计与实现 1.前言 2.技术栈 3.关键源码 4.实现效果 4.1.登录 4.2.文件列表 4.3.上传文件测试 4.3.1.测试图片 4 ...

  7. springboot文件上传下载实战 —— 登录功能、展示所有文件

    springboot文件上传下载实战 创建项目 pom.xml 数据库建表与环境准备 建表SQL 配置文件 application.properties 整体架构 前端页面 登录页面 login.ht ...

  8. springboot:实现文件上传下载实时进度条功能【附带源码】

    0. 引言 记得刚入行的时候,做了一个文件上传的功能,因为上传时间较久,为了用户友好性,想要添加一个实时进度条,显示进度.奈何当时技术有限,查了许久也没用找到解决方案,最后不了了之. 近来偶然想到这个 ...

  9. MinIO入门-02 SpringBoot 整合MinIO并实现文件上传

    SpringBoot 整合MinIO并实现文件上传 1.依赖 <!-- https://mvnrepository.com/artifact/io.minio/minio --> < ...

最新文章

  1. 用C语言解“12-24小时制”题
  2. mac 开机执行命令
  3. 不写技术文档是个什么梗
  4. EOS账户系统(7)权限评估
  5. Could not find a file system implementation for scheme ‘hdfs‘.
  6. java中的JDBC
  7. struts2批量删除
  8. ASP.NET Core中使用GraphQL - 第七章 Mutation
  9. RuntimeError: DataLoader worker (pid(s) 13512, 280, 21040) exited unexpectedly
  10. elasticsearch存储空间不足导致索引只读,不能创建
  11. springcloud不使用数据库微服务启动异常解决
  12. spring jpa mysql集群_微框架:Springboot+Jpa+mysql零基础上手班
  13. 微信公众平台开发(83) 生成带参数二维码
  14. 技术人必备的学习工具
  15. Lingo软件使用教程
  16. 移动云5G消息平台技术架构
  17. VC浏览器相关的学习(七)(BHO捕获鼠标键盘事件)
  18. 【从零学习openCV】IOS7下的人脸检测
  19. Windows下生成dump文件的三种方式
  20. git 撤回 (git版本回退处理)

热门文章

  1. Android Apk瘦身方案1——R.java文件常量内联
  2. 使用Pulseview软件辅助verilog数字设计仿真协议解码
  3. IEEE 754二进制浮点数算术标准
  4. python求平均值,python 怎么求平均值
  5. 使用maven编译打包用javac还是eclipse的jdt的问题
  6. 为什么数码相机可以拍出彩色照片?
  7. 任务型对话系统(一)
  8. APP软件测试点着重详解
  9. 医学图像处理与深度学习入门
  10. Navicat建数据库时字符集与排序规则说明