springboot简单集成上传和下载(带页面)

来学习一下文件上传和下载


一、页面开发

整体思路

登录页

主页


二、库表设计

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for t_files
-- ----------------------------
DROP TABLE IF EXISTS `t_files`;
CREATE TABLE `t_files` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `oldFileName` varchar(255) DEFAULT NULL,
  `newFileName` varchar(255) DEFAULT NULL,
  `ext` varchar(255) DEFAULT NULL,
  `path` varchar(255) DEFAULT NULL,
  `size` varchar(255) DEFAULT NULL,
  `type` varchar(255) DEFAULT NULL,
  `isImg` int(11) NOT NULL,
  `downCounts` varchar(255) DEFAULT NULL,
  `uploadTime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of t_files
-- ----------------------------

-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of t_user
-- ----------------------------

三、环境搭建


四、用户登录开发

这次新建了一个工程,因为 Lombok 用得很习惯,但以前的话,一般只用了@Data@AllArgsConstructor@EqualsAndHashCode等常规注解;那这个Accessors(chain = true)注解是干嘛的呢?

https://www.cnblogs.com/grey-wolf/p/11812528.html

五、用户文件列表

        <tr th:each="f:${file}">
            <td th:text="${f.id}"></td>
            <td th:text="${f.oldFileName}"></td>
            <td th:text="${f.newFileName}"></td>
            <td th:text="${f.ext}"></td>
            <td th:text="${f.path}"></td>
            <td th:text="${f.size}"></td>
            <td th:text="${f.type}"></td>
            <td th:text="${f.isImg}"></td>
            <td th:text="${f.downCounts}"></td>
            <td th:text="${#dates.format(f.uploadTime,'yyyy-MM-dd')}"></td>//日期格式化
            <td><a href="">下载</a>&nbsp;<a href="">在线打开</a>&nbsp;<a href="">删除</a></td>
        </tr>

六、用户文件上传

1、文件上传

记录旧文件名、新文件名、文件后缀、文件大小、文件路径、文件类型、下载次数、下载时间、是否图片

    /**
     * 上传文件并保存到数据库中
     * 文件名lujiahong要和表单中的name属性一一对应
     * 上传的文件存在static里面
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("lujiahong") MultipartFile file,HttpSession session) throws IOException {
        //1、获取文件原始名称
        String oldFileName = file.getOriginalFilename();
        //2、按旧文件名获取文件后缀(创建新文件名名获取文件后缀 ,需要引入依赖包commons-fileupload)
        String extension ="."+ FilenameUtils.getExtension(oldFileName);
        //3、生成新的文件名称(当前时间+UUID+后缀)——UUID里面有符号"-",替换为""
        String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date() )+ UUID.randomUUID().toString().replace("-","")+extension;
        //4、文件大小
        Long size = file.getSize();
        //5、文件类型
        String type = file.getContentType();
        //6、根据日期生成目录
            //通过工具类ResourceUtils去获取静态文件下指定文件的真实路径
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static/files";
            //生成动态日期路径
        String dataFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dateDirPath = realPath + "/" + dataFormat;
            //得到日期目录
        File dateDir = new File(dateDirPath);
        if(!dateDir.exists()) {
            dateDir.mkdirs();
        }
        //7、处理文件上传
        file.transferTo(new File(dateDir,newFileName));
        //8、文件相关数据存入数据库
        Files files = new Files();
        files.setUserId(((User)session.getAttribute("user")).getId());
        files.setOldFileName(oldFileName);
        files.setNewFileName(newFileName);
        files.setExt(extension);
        files.setType(type);
        files.setSize(size);
        files.setPath("/files/"+dataFormat);
        files.setDownCounts("0");
        files.setUploadTime(new Date());
        files.setIsImg(0);
        this.iFilesService.save(files);
        return "redirect:/file/showAll";
    }

2、配置文件上传大小、以及一次性可上传文件大小

    spring: 
      servlet:
        multipart:
        max-file-size: 50MB #设置单个文件大小
        max-request-size: 50MB #设置单次请求文件的总大小
@Configuration
public class MultipartConfig {
    @Bean
    public MultipartConfigElement multipartConfigElement(){
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setMaxFileSize(DataSize.parse("50MB"));//允许上传的文件最大值
        factory.setMaxRequestSize(DataSize.parse("50MB"));// 设置总上传数据总大小
        return factory.createMultipartConfig();
    }
}

3、参考

  1. 参考一
  2. 参考二
  3. 参考三

七、用户上传文件是否是图片判断

1、后台响应前台

public class ResBack {
    public static void response(String msg, HttpServletResponse response){
        try {
            response.setContentType("text/html; charset=UTF-8"); //转码
            PrintWriter out = response.getWriter();
            out.flush();
            out.println("<script>");
            out.println("alert('"+msg+"');");
            out.println("history.back();");
            out.println("</script>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2、后台在线播放

servletContext.contextPath用来获取文件项目中的地址,后面是保存在项目static里面的路径的拼接

            <td th:switch="${f.isImg ne ''}">
                <img th:case="${f.isImg eq '图片'}" th:src="${#servletContext.contextPath+f.path+'/'+f.newFileName}" style="width: 100px;height: 100px">
                <video th:case="${f.isImg eq '视频'}" th:src="${#servletContext.contextPath+f.path+'/'+f.newFileName}" controls="controls" style="width: 100px;height: 100px"></video>
                <audio th:case="${f.isImg eq '音频'}" th:src="${#servletContext.contextPath+f.path+'/'+f.newFileName}" controls="controls" style="width: 100px;height: 100px"></audio>
                <p th:case="${f.isImg eq '未知类型'}">未知类型</p>
            </td>


八、用户下载文件

    @GetMapping("/download")
    public void down(@RequestParam("id") int id,HttpServletResponse response) throws IOException {
        //1、获取文件信息
        Files files = this.iFilesService.getById(id);
        //2、更新下载次数
        files.setDownCounts(files.getDownCounts()+1);
        this.iFilesService.updateById(files);
        //2、根据文件存储路径path和文件名获取文件输出流
        String downPath = ResourceUtils.getURL("classpath:").getPath() + "/static" + files.getPath();
        //3、获取文件输入流
        FileInputStream fileInputStream = new FileInputStream(new File(downPath,files.getNewFileName()));
        //4、附件格式下载设置头部( URLEncoder.encode(files.getOldFileName(),"utf-8") 设置文件名编码风格,避免乱码)
        response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(files.getOldFileName(),"utf-8"));
        //4、获取响应输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //5、文件拷贝
        IOUtils.copy(fileInputStream,outputStream);
        //6、关闭输入输出流
        IOUtils.closeQuietly(fileInputStream);
        IOUtils.closeQuietly(outputStream);
    }

九、用户删除文件

1、前台请求url的写法——thymeleaf

@{/file/download(id=${f.id},openStyle=‘inline’)}相当于file/download?id=30&openStyle=inline

<a th:href="@{/file/download(id=${f.id})}" target="_blank">下载</a>&nbsp;
<a th:href="@{/file/download(id=${f.id},openStyle='inline')}" target="_blank">在线打开</a>
<a th:href="@{/file/delFile(id=${f.id})}">删除</a><

2、在线展示数据

下载还是在线打开(逻辑判断,设置不同请求头即可实现;attachment——下载;inline——在线打开)

response.setHeader(“content-disposition”,“attachment;fileName=文件名”);//下载头部设置

response.setHeader(“content-disposition”,“inline;fileName=文件名”);//预览头部设置

    @GetMapping("/download")
    public void down(String openStyle,@RequestParam("id") int id,HttpServletResponse response) throws IOException {
        //获取打开方式——下载还是在线打开(共用一个接口,逻辑判断,设置不同请求头即可实现;attachment——下载;inline——在线打开)
        openStyle = openStyle == null? "attachment":openStyle;
        //1、获取文件信息
        Files files = this.iFilesService.getById(id);
        //2、更新下载次数
        if("attachment".equals(openStyle)){
            files.setDownCounts(files.getDownCounts()+1);
            this.iFilesService.updateById(files);
        }
        //2、根据文件存储路径path和文件名获取文件输出流
        String downPath = ResourceUtils.getURL("classpath:").getPath() + "/static" + files.getPath();
        //3、获取文件输入流
        FileInputStream fileInputStream = new FileInputStream(new File(downPath,files.getNewFileName()));
        //4、附件格式下载设置头部( URLEncoder.encode(files.getOldFileName(),"utf-8") 设置文件名编码风格,避免乱码)
        response.setHeader("content-disposition",openStyle+";fileName="+ URLEncoder.encode(files.getOldFileName(),"utf-8"));
        //4、获取响应输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //5、文件拷贝
        IOUtils.copy(fileInputStream,outputStream);
        //6、关闭输入输出流
        IOUtils.closeQuietly(fileInputStream);
        IOUtils.closeQuietly(outputStream);
    }

3、删除文件

    @GetMapping("/delFile")
    public String del(int id) throws FileNotFoundException {
        //1、删除本地文件数据
            //获取删除路径
        Files files = this.iFilesService.getById(id);
        String delPath = ResourceUtils.getURL("classpath:").getPath() + "static/" + files.getPath();
        File file = new File(delPath,files.getNewFileName());
        if(file.exists()){
            file.delete();
        }
        //2、删除数据库数据
        this.iFilesService.delFile(id);
        return "redirect:/file/showAll";
    }

十、定时更新下载次数

前端定时调度接口刷新下载次数

<script type="application/javascript" th:src="@{/static/js/jquery-3.5.1.min.js}"></script>
<script>
    $(()=>{
        var time ;
        $('#start').click(()=>{
            time = setInterval(()=>{
            $.get("[[@{/file/showAllJson}]]",(res)=>{
                $.each(res,(index,file)=>{
                    $("#"+file.id).text(file.downCounts)
                })
            })
        },3000);
        })
        $("#stop").click(()=>{
            clearInterval(time)
        })
    })
</script>
<body>
    <button id="start">开启定时更新</button>
    <button id="stop">关闭定时更新</button>
</body>

十一、对上面功能添加

作者一:愿有清风不解语i

我将老师的项目添加了一些小功能:

1、使用Shiro安全框架来做登录认证和拦截;

2、使用SemanticUi来稍微美化了一下界面;

3、在登录界面添加了JS代码,对表单预验证;

4、修复了在没有选择上传文件的情况下,能够上传文件的一个小bug;

5、对密码使用了MD5加密

https://github.com/HaiTang-8/File-Upload/tree/master

作者二:灵器冰

在老师的基础上,

1.增加了多用户登录注册,

2.整合layui框架美化界面和响应事件刷新表格,

3.使用shiro安全框架对页面访问进行控制。

4.为数据表格增加了分页功能。

https://github.com/sdifv/fileStorage

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IQ小王子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值