北京太阳宫网站建设,贵州省建设厅的网站,南阳网站营销外包,张家港百度网站推广1. 上传功能模块
1.1 上传概述
文件上传#xff0c;也称为upload#xff0c;是指将本地图片、视频、音频等文件上传到服务器上#xff0c;可以供其他用户浏览或下载的过程。 文件上传时#xff0c;对页面的form表单有如下要求#xff1a;
表单属性取值说明methodpost必…1. 上传功能模块
1.1 上传概述
文件上传也称为upload是指将本地图片、视频、音频等文件上传到服务器上可以供其他用户浏览或下载的过程。 文件上传时对页面的form表单有如下要求
表单属性取值说明methodpost必须选择post方式提交enctypemultipart/form-data采用multipart格式上传文件typefile使用input的file控件上传
1.2 前端介绍
1). 简单html页面表单
form methodpost action/common/upload enctypemultipart/form-datainput namemyFile typefile /input typesubmit 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 langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title文件上传/title!-- 引入样式 --link relstylesheet href../../plugins/element-ui/index.css /link relstylesheet href../../styles/common.css /link relstylesheet href../../styles/page.css /
/head
bodydiv classaddBrand-container idfood-add-appdiv classcontainerel-upload classavatar-uploaderaction/common/upload:show-file-listfalse:on-successhandleAvatarSuccess:before-uploadbeforeUploadrefuploadimg v-ifimageUrl :srcimageUrl classavatar/imgi v-else classel-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/scriptscript src../../js/index.js/scriptscriptnew 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-ifimageUrl :srcimageUrl classavatar/img
解析通过img标签如何展示图片数据具体的流程 在文件上传成功后在 handleAvatarSuccess 方法中获取文件上传成功之后返回的数据(文件名)然后调用 /common/download?namexxx 进行文件的下载。在这里如果想让上传的照片能够在页面展示出来所以需要在服务端将文件以流的形式写回浏览器。
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?serverTimezoneAsia/ShanghaiuseUnicodetruecharacterEncodingutf-8zeroDateTimeBehaviorconvertToNulluseSSLfalseallowPublicKeyRetrievaltrueusername: 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 RString 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(basePathfileName));} 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();}}
}