File upload and download case based on SpringBoot and Mybatis

Posted by k994519 on Thu, 23 Dec 2021 02:17:59 +0100

File upload and download case based on SpringBoot and Mybatis

This case is based on the actual combat of the [bad programmer] enterprise file upload and download project based on SpringBoot and Mybatis. BiliBili link: https://www.bilibili.com/video/BV1764y1u7gn?p=1

Effect achieved

1. Users need to log in first. We use shiro authentication to log in

2. After logging in, the information uploaded by the user is displayed

Project structure directory

step

1. Create a new database

Here we use Navicat to create the files database. The database has two tables: user table and uploaded file record table:

2. Create a springboot project

After the springboot project is created, the dependencies such as thymeleaf, web, lombok, shiro, etc. are introduced. The specific project is POM The XML file is as follows:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zq</groupId>
    <artifactId>files</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>files</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.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.5.2</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3. Write dao entity class

We create two entity classes, User and UserFile, under the dao package of the project. Here we use lombok to simplify the code. The specific code is as follows:

User.java

package com.zq.dao;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {

    private Integer id; // User id
    private String userName;// user name
    private String password;// User password

}

UserFile.java

package com.zq.dao;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class UserFile {

    private Integer id; // id
    private String oldFileName;// Initial name of uploaded file
    private String newFileName;// Upload file new name
    private String ext;// file extension
    private String path;// File path
    private String size;// file size
    private String type;// file type
    private String isImg;// Is it a picture
    private int downCounts;// amount of downloads
    private Date uploadTime;// Upload time
    private int userId;// User id
}

4. Write dao interface

We create two dao interfaces, UserMapper and UserFileMapper, under the mapper package of the project. The specific code is as follows:

UserMapper.java

package com.zq.mapper;

import com.zq.dao.User;

public interface UserMapper {

    /*User login*/
    User login(String username,String password);

    /*Query user by user name*/
    User findUserByName(String username);
}

UserFileMapper.java

package com.zq.mapper;

import com.zq.dao.UserFile;

import java.util.List;

public interface UserFileMapper {

    //Query all files of the user by Id
    List<UserFile> getFilesByUserId(Integer id);

    //Save file information
    void SaveFile(UserFile userFile);

    //Query the corresponding file by Id
    UserFile getFilesById(Integer id);

    //to update
    void update(UserFile userFile);

    //Delete record by Id
    void delete(Integer id);
}

5. Prepare mapper file

We create UserMapper and UserFileMapper xml files under mapper under mybatis in the resources directory of the project. The specific codes are as follows:

UserMapper.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.zq.mapper.UserMapper">

    <!--User login-->
    <select id="login" resultType="com.zq.dao.User">
        select * from t_user where username=#{username} and password=#{password}
    </select>

    <!--Query users by user name-->
    <select id="findUserByName" resultType="com.zq.dao.User">
        select * from t_user where username=#{username}
    </select>

</mapper>

UserFileMapper.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.zq.mapper.UserFileMapper">

    <!-- According to user ID Query all the stored files of the user -->
    <select id="getFilesByUserId" resultType="com.zq.dao.UserFile">
        select * from t_files where userId=#{id}
    </select>

    <!-- Save file -->
    <insert id="SaveFile">
        INSERT INTO t_files
            VALUES (#{id},
            #{oldFileName},#{newFileName},#{ext},
            #{path},#{size},#{type},#{isImg},
            #{downCounts},#{uploadTime},#{userId});
    </insert>

    <!-- According to the corresponding file id Query file -->
    <select id="getFilesById" resultType="com.zq.dao.UserFile">
        select * from t_files where id = #{id}
    </select>

    <!-- Number of downloads of update files -->
    <update id="update">
        update t_files
        set downCounts = #{downCounts}
        where id = #{id}
    </update>

    <!--according to Id Delete record-->
    <delete id="delete">
        delete from t_files where id = #{id}
    </delete>
</mapper>

6. Write service

Two service interfaces, UserService and UserFileService, are created under the service package of our project. The specific code is as follows:

UserService.java

package com.zq.service;

import com.zq.dao.User;

public interface UserService {

    /*Sign in*/
    User login(String username,String password);

    /*Query user information according to user name*/
    User findUserByName(String username);
}

UserFileService.java

package com.zq.service;

import com.zq.dao.UserFile;

import java.util.List;

public interface UserFileService {

    //Query all corresponding file information according to userId
    List<UserFile> getFilesByUserId(Integer id);

    //Save user information
    void SaveFile(UserFile userFile);

    //Query the corresponding file according to the corresponding Id
    UserFile getFilesById(Integer id);

    //to update
    void update(UserFile userFile);

    void delete(Integer id);
}

Then create an Impl package under the service package, and create two interface implementation classes, UserServiceImpl and UserFileServiceImpl, to implement the methods in the UserService and UserFileService interfaces. The specific code is as follows:

UserServiceImpl.java

package com.zq.service.Impl;

import com.zq.dao.User;
import com.zq.mapper.UserMapper;
import com.zq.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 
     * @param username  user name
     * @param password  password
     * @return  User information
     */
    @Override
    public User login(String username, String password) {
        return userMapper.login(username, password);
    }

    /**
     * 
     * @param username  user name
     * @return  User information
     */
    @Override
    public User findUserByName(String username) {
        return userMapper.findUserByName(username);
    }
}

UserFileServiceImpl.java

package com.zq.service.Impl;

import com.zq.dao.UserFile;
import com.zq.mapper.UserFileMapper;
import com.zq.service.UserFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
public class UserFileServiceImpl implements UserFileService {

    @Autowired
    private UserFileMapper userFileMapper;

    /**
     * 
     * @param id    User id
     * @return  File upload list corresponding to the user
     */
    @Override
    public List<UserFile> getFilesByUserId(Integer id) {
        return userFileMapper.getFilesByUserId(id);
    }


    /**
     * 
     * @param userFile  Upload information
     */
    @Override
    public void SaveFile(UserFile userFile) {
        //Conduct three eye operation to judge whether the file is a picture
        String isImg = userFile.getType().startsWith("image")?"yes":"no";
        System.out.println(isImg);
        userFile.setIsImg(isImg);
        userFile.setDownCounts(0);
        userFile.setUploadTime(new Date());
        userFileMapper.SaveFile(userFile);
    }

    /**
     * 
     * @param id    Upload file id
     * @return
     */
    @Override
    public UserFile getFilesById(Integer id) {
        return userFileMapper.getFilesById(id);
    }

    /**
     * 
     * @param userFile Upload information
     */
    @Override
    public void update(UserFile userFile) {
        userFileMapper.update(userFile);
    }

    /**
     * 
     * @param id Upload file id
     */
    @Override
    public void delete(Integer id) {
        userFileMapper.delete(id);
    }
}

7. Write shiro configuration file

Because we want to use shiro for user login authentication, we need to write shiro configuration information (those who don't know shiro can go to my shiro blog first, SpringBoot integrated Shiro learning (Part 1) ), we create new ShiroConfig and UserRealm files under the config of the project. ShiroConfig is used to configure shiro, while UserRealm is a custom realm, which is used to realize user login authentication and authorization. The specific code is as follows:

ShiroConfig.java

package com.zq.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    //ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();

        //Set up security manager
        bean.setSecurityManager(defaultWebSecurityManager);

        //Add Shiro's built-in filter
        /*
            anon: Access without authentication
            authc: Authentication is required to access
            user: You must have the remember me function to use
            perms: You must have permission on a resource to access it
            role: You must have a role permission to access
         */
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();

        // Indicates that all paths under / file must pass authentication
        filterChainDefinitionMap.put("/file/*","authc");
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        // Set the default login interface
        bean.setLoginUrl("/user");

        return bean;
    }

    //DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        //Associate UserRealm
        securityManager.setRealm(userRealm);

        return securityManager;
    }

    //To create a realm object, you need to customize the class
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }
}

UserRealm.java

package com.zq.config;

import com.zq.dao.User;
import com.zq.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

//Custom UserRealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    //to grant authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    //authentication
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;

        // Find user information by user name
        User user = userService.findUserByName(userToken.getUsername());

        if (user == null){
            //Indicates that the user name is entered incorrectly
            return null;
        }

        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        session.setAttribute("user", user);

        //authentication
        return new SimpleAuthenticationInfo("",user.getPassword(),"");
    }
}

8. Preparation of front-end documents

Two html files, Login and showAll, are created under templates in the resources directory of our project. The ui framework used in our front end is semantic ui, Semantic UI document address , the specific code of the html file is as follows:

Login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>User login interface</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/semantic-ui/2.2.4/semantic.min.css">
    <link rel="stylesheet" th:href="@{/css/me.css}" href="../static/css/me.css">

</head>
<body>

<div class="m-container-small m-padded-tb-massive" style="max-width: 30em !important;">
    <div class="ui container">
        <div class="ui middle aligned center aligned grid">
            <div class="column">
                <h2 class="ui teal image header">
                    <div class="content">
                        Welcome to the user file management system
                    </div>
                </h2>
                <form class="ui large form" method="post" action="#" th:action="@{/user/login}">
                    <div class="ui segment">
                        <div class="field">
                            <div class="ui left icon input">
                                <i class="user icon"></i>
                                <input type="text" name="username" placeholder="user name">
                            </div>
                        </div>
                        <div class="field">
                            <div class="ui left icon input">
                                <i class="lock icon"></i>
                                <input type="password" name="password" placeholder="password">
                            </div>
                        </div>
                        <button class="ui fluid large teal submit button">Sign in</button>
                    </div>

                    <div class="ui error mini message"></div>
                    <div class="ui mini negative message" th:unless="${#strings. Isempty (message)} "th: text =" ${message} "> wrong username and password < / div >

                </form>

            </div>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/jquery@3.2/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/semantic-ui/2.2.4/semantic.min.js"></script>

<script>
    $('.ui.form').form({
        fields : {
            username : {
                identifier: 'username',
                rules: [{
                    type : 'empty',
                    prompt: 'enter one user name'
                }]
            },
            password : {
                identifier: 'password',
                rules: [{
                    type : 'empty',
                    prompt: 'Please input a password'
                }]
            }
        }
    });

</script>
</body>
</html>

showAll.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>User file list page</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/semantic-ui/2.2.4/semantic.min.css">
</head>
<body>
<h2>welcome:<span th:text="${session.user.userName}"></span></h2>
<table class="ui celled table">
    <thead>
        <tr>
            <th colspan="11">File list</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>ID</td>
            <td>Original file name</td>
            <td>File new name</td>
            <td>file extension</td>
            <td>Storage path</td>
            <td>file size</td>
            <td>type</td>
            <td>Picture</td>
            <td>amount of downloads</td>
            <td>Upload time</td>
            <td>operation</td>
        </tr>
        <tr th:each="file : ${files}">
            <td th:text="${file.id}">1</td>
            <td th:text="${file.oldFileName}">aa.txt</td>
            <td th:text="${file.newFileName}">uuid.txt</td>
            <td th:text="${file.ext}">.txt</td>
            <td th:text="${file.path}">/files</td>
            <td th:text="${file.size}">1024</td>
            <td th:text="${file.type}">text/plain</td>
            <!-- th:classappend:Without changing the label class Property, add a class style-->
<!--            <td th:text="${file.isImg}" th:classappend="${file.getIsImg()=='yes'}?'':'negative'">no</td>-->
            <!--
                ${#servletContext.contextPath} get project name
                @{/}            Get project name
            -->
            <td>
<!--                <img th:if="${file.getIsImg()=='yes'}" style="width: 100px" th:src="${#servletContext.contextPath} + ${file.path} + '/' + ${file.newFileName}">-->
                <img th:if="${file.getIsImg()=='yes'}" style="width: 100px" th:src="${file.path} + '/' + ${file.newFileName}">
                <span th:if="${file.getIsImg()!='yes'}" th:text="${file.isImg}"></span>
            </td>
            <td th:text="${file.downCounts}">11</td>
            <td th:text="${#dates.format(file.uploadTime,'yyyy-MM-dd-HH:mm:ss')}">2020-12-12</td>
            <td>
                <a th:href="@{/file/download(id=${file.id})}" href="">download</a>
                <!--@{/file/download(id=${file.id},openStyle='inline' express /file/download?id=${file.id}?openStyle='inline'-->
                <a target="_blank" th:href="@{/file/download(id=${file.id},openStyle='inline')}" href="">Open online</a>
                <!--@{/file/delete(id=${file.id})}express  /file/delete?id=file.id  -->
                <a th:href="@{/file/delete(id=${file.id})}" href="">delete</a>
            </td>
        </tr>
    </tbody>
</table>
<hr>
<h3>Upload file</h3>
<form method="post" enctype="multipart/form-data" th:action="@{/file/upload}">
    <!--be careful name="aaa" To communicate with the background MultipartFile aaa corresponding-->
    <input type="file" name="aaa"> <input type="submit" value="Upload file">
</form>
<!-- th:if There is an inverse property, th:unless,Unless -->
<div class="ui small compact negative message" th:unless="${#strings.isEmpty(errorMessage)}" th:text="${errorMessage}"></div>


<script src="https://cdn.jsdelivr.net/npm/jquery@3.2/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/semantic-ui/2.2.4/semantic.min.js"></script>
</body>
</html>

9. Write controller

We create two controllers, UserController and UserFileController, under the controller package of the project. The specific code is as follows:

UserController.java

package com.zq.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
@RequestMapping("/user")
public class UserController {

    /*Jump to login interface*/
    @GetMapping
    public String loginPage(){
        return "Login";
    }

    /*Login processing*/
    @PostMapping("/login")
    public String login(@RequestParam String username,
                        @RequestParam String password,
                        RedirectAttributes attributes) {

        //Get current user
        Subject subject = SecurityUtils.getSubject();

        //Encapsulate user login data
        UsernamePasswordToken token = new UsernamePasswordToken(username, DigestUtils.md5DigestAsHex(password.getBytes()));

        //Execute the login method. If there is no exception, the execution is successful
        try {
            subject.login(token);
            return "redirect:/file/showAll";
        } catch (UnknownAccountException e) {
            //Indicates that the user name does not exist
            attributes.addFlashAttribute("message","Wrong user name or password");
            return "redirect:/user";
        } catch (IncorrectCredentialsException e){
            //Indicates that the password is incorrect
            attributes.addFlashAttribute("message","Wrong user name or password");
            return "redirect:/user";
        }
    }
}

UserFileController.java

package com.zq.controller;

import com.zq.dao.User;
import com.zq.dao.UserFile;
import com.zq.service.UserFileService;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping("/file")
public class UserFileController {

    @Autowired
    private UserFileService userFileService;

    /*Display all files uploaded by the current login user*/
    @GetMapping("/showAll")
    public String findAll(HttpSession session, Model model){
        //Get the Id in the logged in session
        User user = (User) session.getAttribute("user");
        List<UserFile> files = userFileService.getFilesByUserId(user.getId());
        model.addAttribute("files",files);
        return "showAll";
    }


    //Process the uploaded files and save the file information to the database
    @PostMapping("/upload")
    public String upload(MultipartFile aaa, HttpSession session, RedirectAttributes attributes) throws IOException {

        if (aaa.getContentType().equals("application/octet-stream")){
            System.out.println(1);
            attributes.addFlashAttribute("errorMessage","Cannot upload empty file!");
        }else {
            //Gets the currently logged in object
            User user = (User) session.getAttribute("user");

            //Gets the original name of the file
            String oldFileName = aaa.getOriginalFilename();

            //Gets the suffix of the file
            String extension = "." + FilenameUtils.getExtension(aaa.getOriginalFilename());

            //Generate a new file name
            String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + UUID.randomUUID().toString().replace("-","").substring(6) + extension;

            //Get file size
            long size = aaa.getSize();

            //file type
            String type = aaa.getContentType();

            //The process generates directories based on dates
            String realPath = ResourceUtils.getURL("classpath:").getPath() + "static/files";
            String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            String dateDirPath = realPath + "/" + format;
            // /E:/Desktop/File-Upload/target/classes/static/files/2021-12-21
            System.out.println(dateDirPath);
            File dataDir = new File(dateDirPath);
            /*If the directory does not exist, create it*/
            if (!dataDir.exists()){
                dataDir.mkdirs();
            }

            //Process file upload
            aaa.transferTo(new File(dataDir,newFileName));

            UserFile userFile = new UserFile();
            userFile.setOldFileName(oldFileName);
            userFile.setNewFileName(newFileName);
            userFile.setExt(extension);
            userFile.setSize(String.valueOf(size));
            userFile.setType(type);
            userFile.setPath("/files/"+format);
            userFile.setUserId(user.getId());

            //Save file to database
            userFileService.SaveFile(userFile);
        }

        return "redirect:/file/showAll";
    }

    //File download
    @GetMapping("/download")
    public void download(Integer id,String openStyle,HttpServletResponse response) throws IOException {
        //Get file information
        UserFile userfile = userFileService.getFilesById(id);
        //Judge whether users open or download online (attachment download if openStyle is attachment, online open if openStyle is inline))
        openStyle = openStyle == null ? "attachment" : openStyle;
        if ("attachment".equals(openStyle)){
            //Update file downloads
            userfile.setDownCounts(userfile.getDownCounts()+1);
            userFileService.update(userfile);
        }
        //Obtain the file input stream according to the file name in the file information and the file storage path
        String realpath = ResourceUtils.getURL("classpath:").getPath() + "/static" + userfile.getPath();
        //Get file input stream
        FileInputStream is = new FileInputStream(new File(realpath, userfile.getNewFileName()));
        //If openStyle is attachment, it is attachment download; if openStyle is inline, it is online open)
        response.setHeader("content-disposition",openStyle+";fileName="+ URLEncoder.encode(userfile.getOldFileName(),"UTF-8"));
        //Get response output stream
        ServletOutputStream os = response.getOutputStream();
        //File copy
        IOUtils.copy(is,os);
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);
    }

    //Delete file information
    @GetMapping("/delete")
    public String delete(Integer id) throws FileNotFoundException {
        //Query information by Id
        UserFile userFile = userFileService.getFilesById(id);

        //Delete file
        String realpath = ResourceUtils.getURL("classpath:").getPath() + "/static" + userFile.getPath();
        File file = new File(realpath, userFile.getNewFileName());
        if (file.exists()){
            file.delete();//Delete now
        }

        //Delete discipline from database
        userFileService.delete(id);
        return "redirect:/file/showAll";
    }
}

10. Prepare project configuration file

We write the application of the project YML configuration file, the specific code is as follows:

application.yml

server:
  port: 8081

spring:
  thymeleaf:
    # Close thymeleaf cache to facilitate testing
    cache: false

  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/files?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456

  #Set the size of the uploaded file
  # Max file size = 10MB is to set the size of a single file, and Max request size = 100MB is to set the total size of a single requested file
  #If you want to not limit the size of file upload, set both values to - 1
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 100MB


mybatis:
  # mybatis profile location
  config-location: classpath:mybatis/mybatis-config.xml
  # mapper location
  mapper-locations: classpath:mybatis/mapper/*.xml

11. Prepare project startup class and start

We write the startup class of the project. The specific code is as follows:

FilesApplication.java

package com.zq;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.zq.mapper")
public class FilesApplication {

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

Then we start the project,

After launching the project successfully, we enter it in the browser http://localhost:8081/user You can enter the project login page to log in,

After logging in, the information uploaded by the user is displayed

File saving location after successful upload:

Source code acquisition

So far, our case of file upload and download based on SpringBoot and Mybatis has been explained. Source code and database files can be obtained by paying attention to my WeChat official account, I love learning, hee hee, reply to the keyword "file upload and download case".

Topics: Mybatis Shiro Spring Boot