IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> SpringBoot+Vue+ElementUI实现文件的上传和下载 并将 文件信息存入数据库 -> 正文阅读

[JavaScript知识库]SpringBoot+Vue+ElementUI实现文件的上传和下载 并将 文件信息存入数据库

一、参考文档

springboot 文件MultipartFile上传路径问题 | 橙熟^ _ ^-CSDN(原本采用绝对路径,参考该文章改成相对路径)

组件 | Element


二、导入依赖和配置application.yml文件

1、在pom.xml中导入依赖。

采用了mybatis-plus,需要导入依赖。

<!-- mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>

2、导入依赖配置application.yml文件。

server:
  port: 8800
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/数据库名?serverTimezone=GMT%2B8
    username: root
    password: 123456
mybatis-plus:
  # mapper扫描
  mapper-locations: classpath*:mapper/**/*.xml
  configuration:
    # 打印sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

files:
  upload:
  	# 文件相对路径
    path: ./src/main/resources/images/


三、创建数据库表和创建实体类

1、创建数据库files表。

DROP TABLE IF EXISTS `files`;
CREATE TABLE `files`  (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '文件id',
  `files_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件名称',
  `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件类型',
  `size` double(32, 2) NULL DEFAULT NULL COMMENT '文件大小(KB)',
  `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '下载链接',
  `md5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件md5',
  `enable` tinyint NULL DEFAULT 1 COMMENT '链接是否可用(1:是 0:否)',
  `is_delete` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除(1:是 0:否)',
  `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
  `update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `name`(`files_name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '文件表' ROW_FORMAT = Dynamic;

2、创建实体类Files。

@Data
@TableName("files")
public class Files implements Serializable {
 	@TableId(type = IdType.AUTO)
    private Integer id;//编号
    
    private String filesName;//文件名称

    private String type;//文件类型

    private Double size;//文件大小

    private String url;//下载链接

    private String md5;//文件MD5

    private Boolean enable;//链接是否可用(1:是 0:否)

    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;//创建时间

    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;//更新时间

    @TableLogic()
    private Integer isDelete;//是否删除(1:是 0:否)
}

四、创建Mapper层

1、创建FilesMapper。

@Mapper
public interface FilesMapper extends BaseMapper<Files> {

}

2、创建FilesMapper.xml。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hyc.nsms.mapper.FilesMapper">

</mapper>

五、创建业务层

1、创建FilesService。

public interface FilesService extends IService<Files> {
    //上传文件
    String upload(MultipartFile file);

    //下载文件
    void download(String filesUUID, HttpServletResponse response);
}

2、创建FilesServiceImpl。

@Service
public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements FilesService {
    @Value("${files.upload.path}")
    private String filesUploadPath;//获取文件路径

    @Override
    public String upload(MultipartFile file) {
        //将相对路径转化为绝对路径
        String destPath = new File(filesUploadPath).getAbsolutePath();
        //文件夹路径名称
        String originalFilename = file.getOriginalFilename();
        //文件大小
        double size = file.getSize();
        //文件类型
        String type = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();

        //使用uuid生成随机唯一值
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //新的文件名称,uuid+文件类型
        String fileUuid = uuid + "." + type;
        //新的文件地址,绝对路径+新的文件名称
        File uploadFile = new File(destPath + "/" + fileUuid);

        //判断配置的文件目录是否存在,若不存在则创建一个新的文件目录
        File parentFile = uploadFile.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }

        try {
            String url;
            //获取文件的md5,通过对比文件md5,防止上传相同内容的文件
            String md5 = DigestUtils.md5DigestAsHex(file.getInputStream());
            //通过MD5来查询文件
            Files dbFiles = this.getFileByMD5(md5);
            if (dbFiles != null) {//如果数据库存在相同文件,直接获取url
                url = dbFiles.getUrl();
            } else {//如果数据库不存在相同文件,先存储到本地磁盘,再设置文件url
                file.transferTo(uploadFile);//把获取到的文件存储带磁盘目录
                url = "http://localhost:8800/files/" + fileUuid;//设置文件url
            }

            //将文件存储到数据库
            Files saveFile = new Files();
            saveFile.setFilesName(originalFilename);
            saveFile.setType(type);
            saveFile.setSize(size / 1024);//(单位:KB)
            saveFile.setUrl(url);
            saveFile.setMd5(md5);
            //保存操作
            save(saveFile);
            
			//返回文件下载路径url
            return url;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    //将文件以流的形式一次性读取到内存,通过响应输出流输出到前端
    @Override
    public void download(String filesUUID, HttpServletResponse response) {
        try {
            //根据文件的唯一标识码获取文件
            File uploadFile = new File(filesUploadPath + filesUUID);

            //读取文件的字节流
            FileInputStream fileInputStream = new FileInputStream(uploadFile);
            //将文件写入输入流
            InputStream inputStream = new BufferedInputStream(fileInputStream);

            byte[] buffer = new byte[inputStream.available()];
            inputStream.read(buffer);
            inputStream.close();


            //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.png"
            //filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filesUUID, "UTF-8"));
            response.setContentType("application/octet-stream");

            //设置输出流的格式
            ServletOutputStream os = response.getOutputStream();
            os.write(buffer);
            
            //关闭
            fileInputStream.close();
            os.flush();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //通过文件MD5查询文件
    private Files getFileByMD5(String md5) {
        //查找数据库是否已经存在一样的图片
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        List<Files> filesList = list(queryWrapper);
        return filesList.size() == 0 ? null : filesList.get(0);
    }
}

六、创建控制层和全局统一返回结果类

1、创建控制层FilesController。

@RestController
@RequestMapping("/files")
public class FilesController {
    @Autowired
    private FilesService filesService;

    @PostMapping("upload")
    public Result upload(@RequestParam MultipartFile file) {
        //获取上传文件
        String url = filesService.upload(file);
        return Result.ok(url);
    }

    @GetMapping("/{filesUUID}")
    public void download(@PathVariable String filesUUID, HttpServletResponse response) {
        //下载文件
        filesService.download(filesUUID, response);
    }

2、创建返回类Result。

//全局统一返回结果类
@Data
public class Result<T> {
    //返回码
    private Integer code;

    //返回消息
    private String message;

    //返回数据
    private T data;

    public Result() {
    }

    protected static <T> Result<T> build(T data) {
        Result<T> result = new Result<T>();
        if (data != null)
            result.setData(data);
        return result;
    }

    public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
        Result<T> result = build(body);
        result.setCode(resultCodeEnum.getCode());
        result.setMessage(resultCodeEnum.getMessage());
        return result;
    }

    public static <T> Result<T> build(Integer code, String message) {
        Result<T> result = build(null);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    public static <T> Result<T> ok() {
        return Result.ok(null);
    }

    //操作成功
    public static <T> Result<T> ok(T data) {
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.SUCCESS);
    }

    public static <T> Result<T> fail() {
        return Result.fail(null);
    }

    //操作失败
    public static <T> Result<T> fail(T data) {
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.FAIL);
    }

    public Result<T> message(String msg) {
        this.setMessage(msg);
        return this;
    }

    public Result<T> code(Integer code) {
        this.setCode(code);
        return this;
    }

    public boolean isOk() {
        if (this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
            return true;
        }
        return false;
    }
}

七、使用Postman测试

1、测试上传文件。

  1. 上传成功并返回url。
    在这里插入图片描述2. 查看数据库。在这里插入图片描述

2、测试下载文件。

  1. 直接将返回的url复制到搜索引擎。
    在这里插入图片描述
  2. 文件下载成功。
    在这里插入图片描述

八、前端Vue+ElementUI

1、上传

  1. 使用el-upload标签。

     <el-upload action="http://localhost:8800/files/upload"
                :show-file-list="false"
                :on-success="handleUploadSuccess"
                style="display: inline-block">
     	 <el-button type="primary" icon="el-icon-upload" style="margin-right: 10px">上传</el-button>
    </el-upload>
    
  2. 文件上传成功时的钩子handleUploadSuccess。

    methods: {
    	//上传文件按钮
    	handleUploadSuccess(res) {
        	if (res.code === 200) {
            	this.$message.success("上传成功")
                //this.getList()//刷新页面
    		} else {
    			this.$message.error("上传失败")
            }
    	},
    }
    

2、下载

  1. 写个按钮el-button。
    <template slot-scope="scope">
        <el-button type="primary" icon="el-icon-download" @click="download(scope.row.url)">下载</el-button>           
    </template>
    
  2. 定义方法download。
    methods: {
    	//下载文件
        download(row) {
        	file.downloadFiles(row).then(res => {
            	console.log(res)
            })
        },
    }
    
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:09:15  更:2022-05-05 11:14:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:27:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码