springboot文件上传_下载_删除_在线打开_ajax定时更新数据

流程展示
在这里插入图片描述
在这里插入图片描述数据库表
在这里插入图片描述在这里插入图片描述
图1 跳转登录Controller (因为用到了thymeleaf,需要从接口进入,为了初始化页面数据)


```java
/**
 * 跳转到登录页面
 */
@Controller
public class IndexController {
    @GetMapping("index")
    public String toLogin() {
        return "login";
    }
}

登录Controller

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * 用户登录方法
     *
     * @return
     */
    @PostMapping("login")
    public String login(User user, HttpSession session) {
        User userDb = userService.login(user);
        if (userDb != null) {
            session.setAttribute("user", userDb);
            return "redirect:/file/showAll";
        } else {
            return "login";
        }
    }
}

文件上传Controller

@Controller
@RequestMapping("/file")
public class FileController {
    @Autowired
    private FileService fileService;

    /**
     * 根据用户id,查询对应用户所有的上传的文件
     *
     * @param session
     * @param model
     * @return
     */
    @GetMapping("/showAll")
    public String findAll(HttpSession session, Model model) {
        //用户登录之后就会用用户信息储存在Session中,可以从session中取出用户的id进行文件查询
        User user = (User) session.getAttribute("user");
        List<File> files = fileService.findFiles(user.getId());
        if (files != null) {
            //将查到的文件放在model中
            model.addAttribute("files", files);
        }
        return "showAll";
    }

    /**
     * 上传文件  并保存文件信息到数据库
     *
     * @param file
     */
    @PostMapping("/upload")
    public String uploadFile(MultipartFile file, HttpSession session) throws IOException {
        fileService.saveFile(file, session);
        return "redirect:/file/showAll";
    }

    /**
     * 下载对应用户下的指定文件
     * 在线打开图片也是用这个借口,下载的时候 响应头中设置 类型为 inline则为在线打开  attachment为 附件下载
     * @param id 文件id
     */
    @GetMapping("/download")
    public void downloadFile(HttpServletResponse response, String openStyle, Integer id) throws IOException {
        fileService.findByFileId(id, openStyle, response);
        /*//因为下载 会更新下载次数,操作之后,重新加载列表
        return "redirect:/file/showAll";*/
    }

    /**
     * 删除文件
     * @param id  文件id
     */
    @GetMapping("/delete")
    public String deleteFile(Integer id) throws FileNotFoundException {
        fileService.deleteFile(id);
        //删除完之后重新查询列表
        return "redirect:/file/showAll";
    }

    /**
     * ajax请求传所有的文件信息,设置3秒执行一次,去更新下载次数
     * @param session session 为了从session中获取到用户
     * @return
     */
    @GetMapping("/showAllJson")
    @ResponseBody
    public List<File> showAllJson(HttpSession session) {
        //用户登录之后就会用用户信息储存在Session中,可以从session中取出用户的id进行文件查询
        User user = (User) session.getAttribute("user");
        //根据用户id查询 文件列表
        List<File> files = fileService.findFiles(user.getId());
        if (files != null) {
            //返回查询的文件列表
            return files;
        }
        return null;
    }
}

用户登录Service接口

/**
 * 用户登录信息查询
 */
public interface UserService {
    User login(User user);
}

文件上传Service接口

/**
 * 文件上传的一些接口
 */
public interface FileService {
    List<File> findFiles(Integer userId);

    void saveFile(MultipartFile file, HttpSession session) throws IOException;

    void findByFileId(Integer id,String openStyle, HttpServletResponse response) throws IOException;

    void deleteFile(Integer id) throws FileNotFoundException;
}

用户登录查询用户信息ServiceImpl实现类

@Service
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    /**
     * 用户登录查询用户信息
     * @param user
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS) //使查询也支持事务
    public User login(User user) {
        User userDb = userMapper.login(user);
        return userDb;
    }
}

文件上传ServiceImpl实现类

@Service
@Transactional
public class FileServiceImpl implements FileService {
    @Autowired
    private FileMapper fileMapper;

    /**
     * 根据用户的id查询当前用户下的所有上传的文件
     *
     * @param userId
     */
    @Override
    public List<File> findFiles(Integer userId) {
        List<File> files = fileMapper.findFiles(userId);
        return files;
    }

    /**
     * 根据用户id保存用户上传的文件信息
     *
     * @param file
     */
    @Override
    public void saveFile(MultipartFile file, HttpSession session) throws IOException {
        User user = (User) session.getAttribute("user");
        //获取文件的名称 旧名称
        String oldFileName = file.getOriginalFilename();

        //文件的后缀名, 用到FilenameUtils工具类 ,获取的扩展名
        String extensionName = "." + FilenameUtils.getExtension(oldFileName);

        //文件的新名称 时间戳加上随机数 加上后缀名
        String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + UUID.randomUUID().toString().replace("-", "") + extensionName;

        //文件大小
        long fileSize = file.getSize();

        //文件类型
        String fileType = file.getContentType();

        //文件储存的路径  在resorce目录下的static/files
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static/files";
        //根据日期生成文件夹储存文件
        String dateFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dateDirPath = realPath + "/" + dateFormat;

        java.io.File dateDir = new java.io.File(dateDirPath);
        //如果日文文件夹不存在就创建文件夹
        if (!dateDir.exists()) {
            dateDir.mkdirs();
        }
        //储存复制文件,储存
        file.transferTo(new java.io.File(dateDir, newFileName));

        //文件信息储存到数据库
        File files = new File();
        files.setOldFileName(oldFileName);
        files.setNewFileName(newFileName);
        files.setExt(extensionName);
        files.setPath("/files/" + dateFormat);
        files.setSize(String.valueOf(fileSize));
        files.setType(fileType);
        //是否为图片,文具文件类型获取,如果是图片的话,文件类型是以image开头的
        String isImage = fileType.startsWith("image") ? "是" : "否";
        files.setIsImage(isImage);

        //上传日期
        files.setUploadTime(new Date());

        //用户id
        files.setUserId(user.getId());
        fileMapper.saveFile(files);
    }

    /**
     * 文件下载
     *
     * @param id 文件id
     */
    @Override
    public void findByFileId(Integer id, String openStyle, HttpServletResponse response) throws IOException {
        //判断是否携带openStyle,如果没有下载就是附件下载,有携带的话就是携带的inline ,也可都携带参数,此处做判断即可
        String download_or_Inline = openStyle == null ? "attachment" : openStyle;
        File fileDb = fileMapper.findByFileId(id);
        if (fileDb != null) {
            //先获取项目所在绝对路径    //获取文件储存的文件夹 以及文件的名称
            String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static" + fileDb.getPath();
            //通过新文件名得到文件
            String newFileName = fileDb.getNewFileName();
            //给用户的是之前的文件名
            String oldFileName = fileDb.getOldFileName();
            //输入流
            FileInputStream is = new FileInputStream(new java.io.File(realPath, newFileName));

            //做判断,如果是图片才能在线打开,不是图片只能下载
            if (download_or_Inline.equals("inline") && !fileDb.getType().startsWith("image")) {
                //附件只能进行下载
                response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(oldFileName, "utf-8"));
            } else {
                //附件下载  inline是在线打开  attachment 是附件下载
                response.setHeader("content-disposition", download_or_Inline+";filename=" + URLEncoder.encode(oldFileName, "utf-8"));
            }
            //文件输出,响应回去的,添加response
            ServletOutputStream os = response.getOutputStream();
            //文件复制  调用IOUtils工具类直接复制
            IOUtils.copy(is, os);

            //在线打开,不计下载次数
            if (download_or_Inline.equals("attachment")) {
                //文件复制之后,下载次数 + 1
                fileDb.setDownCounts(fileDb.getDownCounts() + 1);
                //将修改后的下载数量跟新到数据库
                fileMapper.updateDownloadCounts(fileDb);
            }

            //关闭流 释放资源
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(os);
        }
    }

    /**
     * 根据id删除文件
     * @param id
     */
    @Override
    public void deleteFile(Integer id) throws FileNotFoundException {
        //删除文件,要先查到文件信息,删除储存的文件,然后删除数据库文件信息
        File fileDb = fileMapper.findByFileId(id);
        //获取文件的位置   文件储存的位置:  resource(本项目下)     /sttic/siles/xxxxxx.jsp
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "static";
        //获取文件
        java.io.File file = new java.io.File((realPath), fileDb.getNewFileName());
        //判断如果文件存在就删除,不存在不要重复操作
        if (file.exists()) {
            file.delete();
        }

        //删除数据库中的文件信息
        fileMapper.deleteFile(id);
    }
}

用户登录信息查询mapper

/**
 * 查询用户信息
 */
@Mapper
public interface UserMapper {
    User login(User user);
}

文件上传mapper

public interface FileMapper {
    //根据用户id查询文件列表
    List<File> findFiles(Integer userId);

    //根据用户id,保存上传的文件信息
    void saveFile(File file);

    //根据文件id查找文件
    File findByFileId(Integer id);

    //更新下载次数
    void updateDownloadCounts(File fileDb);

    //删除文件
    void deleteFile(Integer id);
}

用户登录查询用户信息mapper.xml

<mapper namespace="com.test.mapper.UserMapper">
    <select id="login" resultType="User">
        select id,`name`,password
        from `user` where `name` =#{name} and password = #{password}
    </select>

文件上传mapper.xml

<mapper namespace="com.test.mapper.FileMapper">
    <!--根据用户id查询 用户所有上传的文件-->
    <select id="findFiles" resultType="File">
        select id,oldFileName,newFileName,ext,path,size,type,isImage,downCounts,uploadTime,userId
        from files where userId = #{userId}
    </select>
    <!--储存用户上传的文件-->
    <insert id="saveFile" parameterType="File">
        insert into files values(#{id}, #{oldFileName}, #{newFileName}, #{ext}, #{path}, #{size}, #{type}, #{isImage}, #{downCounts}, #{uploadTime}, #{userId})
    </insert>

    <!--根据文件id查询文件-->
    <select id="findByFileId" resultType="File">
        select id,oldFileName,newFileName,ext,path,size,type,isImage,downCounts,uploadTime,userId
        from files where id = #{id}
    </select>

    <!--更新下载次数-->
    <update id="updateDownloadCounts" parameterType="File" >
        update files set downCounts = #{downCounts} where id = #{id}
    </update>

    <!--删除文件-->
    <delete id="deleteFile" >
        delete from files where id = #{id}
    </delete>

用户 实体类

@Data
public class User {
    private Integer id;
    private String name;
    private String password;
}

文件信息实体类

@Data
public class File {
    /* `id` int(8) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `oldFileName` varchar(200) DEFAULT NULL COMMENT '旧文件名称',
  `newFileName` varchar(300) DEFAULT NULL COMMENT '新文件名称',
  `ext` varchar(20) DEFAULT NULL COMMENT '扩展名',
  `path` varchar(300) DEFAULT NULL COMMENT '路径',
  `size` varchar(200) DEFAULT NULL COMMENT '文件大小',
  `type` varchar(120) DEFAULT NULL COMMENT '文件类型',
  `isImage` varchar(8) DEFAULT NULL COMMENT '是否为图片',
  `downCounts` int(6) DEFAULT NULL COMMENT '下载次数',
  `uploadTime` datetime DEFAULT NULL COMMENT '上传时间',
  PRIMARY KEY (`id`)*/
    private Integer id;
    private String oldFileName;
    private String newFileName;
    private String ext;
    private String path;
    private String size;
    private String type;
    private String isImage;
    private Integer downCounts = 0;
    private Date   uploadTime;
    private Integer userId;
}

启动器

@SpringBootApplication
@MapperScan("com.test.mapper")
public class FilesUploadApplication {

    public static void main(String[] args) {
        SpringApplication.run(FilesUploadApplication.class, args);
    }

}

pom.xml依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.test</groupId>
    <artifactId>files_upload</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>files_upload</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--  mysql 数据库连接 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--文件上传的工具类,可以获取文件后缀等数据-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

application.yml配置文件

server:
  port: 8000
spring:
  application:
    name: files   # jwt
  datasource:     #数据库相关配置
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8
    username: root
    password: root
  thymeleaf:       #静态页相关配置
    cache: false
    suffix: .html
    encoding: utf-8
    prefix: classpath:/templates/
mybatis:
  type-aliases-package: com.test.entity   #包映射
  mapper-locations: com.test.mapper/*.xml  #xml与mapper的映射
  configuration:
    map-underscore-to-camel-case: true   #驼峰

前端文件放置位置;注意要添加jquery到resource/static/js目录下,
前端页面用到了thymeleaf需要在页面上引入<html lang=“en” xmlns:th="http://www.thymeleaf.org>"

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210601220941446.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjY0OTA1NA==,size_16,color_FFFFFF,t_70#pic_center
前端页面结构
在这里插入图片描述

用户登录页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户登录页面</title>
</head>
<body>
<h1>用户登录:</h1>
<form th:action="@{/user/login}" method="post">
   username: <input type="text" name="name"><br>
   password:   <input type="text" name="password"><br>
    <input type="submit" value="登录">
</form>

</body>
</html>

文件列表展示页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>展示文件的列表</title>
    <!--js文件引入   也可用thymeleaf 引入 <script th:src="@{/js/jquery-3.3.1.js}"></script>-->
    <script th:src="@{/js/jquery-3.3.1.min.js}"></script>
    <script>
        /*发送ajax请求,修改下载次数,运用场景具体结合,异步请求    定时3秒发一次ajax请求
        * [[@{/file/findAllJson}]]  为thymeleaf 异步请求url的方式
        *  */
        $(function () {
            /*start 点击事件开启定时更新下载次数  定时任务赋值给time  可以添加关闭定时任务操作*/
            var time;
            $("#start").click(function () {
                console.log("开启定时更新下载次数...")
                time = setInterval(function () {
                    $.get("[[@{/file/showAllJson}]]",function (result) {
                        /*控制台打印回调数据*/
                        /*console.log(result);*/
                        /*给下载次数设置一个id,值为当前文件id ,为了,将异步获取到的所有数据,进行遍历,得到指定的id,然后进行下载次数的定时 修改*/
                        $.each(result,function (index, file) {
                            $("#" + file.id).text(file.downCounts);
                        })
                    });
                }, 3000);
            });
            $("#stop").click(function () {
                console.log("结束定时更新下载次数...")
                clearInterval(time);
            });
        });
    </script>
</head>
<body>
<h1>欢迎: <span th:if="${session.user!=null}" th:text="${session.user.name}"></span></h1>
<h3>文件列表 :</h3>
<button id="start" >开启定时更新</button>
<button id="stop" >结束定时更新</button>
<table border="1px">
    <tr>
        <th>ID</th>
        <th>文件原始名称</th>
        <th>文件新名称</th>
        <th>文件后缀</th>
        <th>储存路径</th>
        <th>文件大小</th>
        <th>类型</th>
        <th>是否是图片</th>
        <th>下载次数</th>
        <th>上传时间</th>
        <th>操作</th>
    </tr>
    <tr th:each="file,fileStat:${files}">
        <td><span th:text="${file.id}"/></td>
        <td><span th:text="${file.oldFileName}"/></td>
        <td><span th:text="${file.newFileName}"/></td>
        <td><span th:text="${file.ext}"/></td>
        <td><span th:text="${file.path}"/></td>
        <td><span th:text="${file.size}"/></td>
        <td><span th:text="${file.type}"/></td>
        <!--是图片就将图片显示出来,不是图片就显示否-->
        <td>
            <!--<span th:text="${file.isImage}"/>-->
            <img style="width: 100px; height: 100px" th:if="${file.isImage} == '是'"
                 th:src="${#servletContext.contextPath} + ${file.path} +'/' + ${file.newFileName}" alt="">
            <span th:if="${file.isImage} != '是'" th:text="${file.isImage}"></span>
        </td>
        <td><span th:id="${file.id}"  th:text="${file.downCounts}"/></td>
        <td><span th:text="${#dates.format(file.uploadTime,'yyyy-MM-dd')}"/></td>
        <td>
            <a th:href="@{/file/download(id=${file.id})}">下载</a>
            <!--传递参数后台进行判断,如果携带openStyle,就赋值给打开方式,inline是在线打开-->
            <a th:href="@{/file/download(id=${file.id},openStyle='inline')}">在线打开</a>
            <a th:href="@{/file/delete(id=${file.id})}">删除</a>
        </td>
    </tr>
</table>
<h3>上传文件:</h3>
<form th:action="@{/file/upload}" method="post" enctype="multipart/form-data">
    <input type="file" name="file"> <input type="submit" value="上传文件">
</form>
</body>
</html>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值