Upload, download and online preview of files based on SpringBoot (SpringBoot demo)

Posted by srdva59 on Sun, 09 Jan 2022 16:02:33 +0100

In the java field, SpringBoot is a very useful framework that can quickly build web projects. Here is a record of using SpringBoot to upload, download and preview files online.

1. Create database and database tables

This paper mainly uses the user and the files to which the user belongs, so we only need to design the user table and file table.

User table t_user

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(80) DEFAULT NULL,
  `password` varchar(80) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC

insert into t_user(username, password) values("pikacho", "123456");

File table t_files

CREATE TABLE `t_files` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `file_name` varchar(200) DEFAULT NULL,
  `ext` varchar(20) DEFAULT NULL,
  `path` varchar(300) DEFAULT NULL,
  `size` bigint(64) DEFAULT NULL,
  `type` varchar(120) DEFAULT NULL,
  `download_counts` int(6) DEFAULT NULL,
  `upload_time` datetime DEFAULT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  CONSTRAINT `t_files_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

2. Create a SpringBoot project

Needless to say here, use IDEA to create a SpringBoot project, delete redundant and useless files, and keep the project structure simple.

Simply create a controller and start the project to test whether the SpringBoot project is built successfully.

@Controller
public class HelloController {

    @RequestMapping("hello")
    @ResponseBody
    public String hello(){
        return "hello SpringBoot";
    }
}
 

Access project: http://localhost:8080/hello , the following screen appears, indicating that the project can run successfully; Ensure the successful operation of the project before considering the development function.

3. Add the dependencies required by the project and configure the basic environment

pom.xml dependency

       <dependencies>
        <!-- thymeleaf Dependency of template engine-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- SpringBoot of web Project dependency-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- lombok Dependency is used to create entity classes without adding constructors manually, setter Other methods-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--mybatis rely on-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <!--Database connection-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>

        <!-- File upload dependency-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

         <!-- druid Database connection pool dependency-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.19</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

application.yml master profile

spring:
  application:
    name: fileStorage
  thymeleaf:
    cache: false
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/fileservice?serverTimezone=Asia/Shanghai&userUnicode=true&characterEncoding=utf-8
    username: root
    password: root

  server:
    port: 8080


  mybatis:
    mapper-locations: classpath:mybatis/mapper/*.xml
    type-aliases-package: com.pikacho.entity

After adding dependencies and configuring the main configuration file, the basic environment required to complete the functions of the project has been built. Start the project to test whether the project can run normally; The following screen shows that the basic environment of the project is successfully built.

4. User login, logout and registration functions

4.1. Complete login function

Even a very simple demo project needs a front-end page. For a back-end developer, it is very painful and difficult to write the front-end page layout and style by himself (I really can't write it!). Therefore, the layui framework is used here to quickly build front-end pages. Of course, this is just a simple use of the framework. You want to use it skillfully. Further study is needed.

1. Introducing layui

Add the files required by layui to the static folder

 2. Create login page

login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>login</title>
    <link rel="stylesheet" th:href="@{/css/layui.css}">
</head>
<body>

<div class="layui-container">
    <div class="layui-row" style="margin-top: 80px;">
        <div class="layui-col-lg4 layui-col-lg-offset4">
            <h1 style="margin:20px; text-align: center"> Please login </h1>
            <form class="layui-form" th:action="@{/user/login}" , method="post">
                <div class="layui-form-item">
                    <p style="color: red; text-align: center" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">user name</label>
                    <div class="layui-input-block">
                        <input class="layui-input" type="text" name="username" required autocomplete="false">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">password</label>
                    <div class="layui-input-block">
                        <input class="layui-input" type="password" name="password" required autocomplete="false">
                    </div>
                </div>
                <div class="layui-form-item">
                    <div class="layui-input-block">
                        <button class="layui-btn" lay-submit lay-filter="formDemo">Log in now</button>
                        <button type="reset" class="layui-btn layui-btn-primary">Reset</button>
                    </div>
                </div>
            </form>
            <div style="float:right">
                <a th:href="@{/user/toRegister}">To register</a>
            </div>
        </div>
    </div>
</div>

<script th:src="@{/layui.js}"></script>
<script>
    //Generally, it is written directly in a js file
    layui.use(['layer', 'form'], function(){
        var layer = layui.layer
            ,form = layui.form;
    });
</script>
</body>
</html>

UserController.java

    /**
     * Go to the login page
     * @return
     */
    @RequestMapping("toLogin")
    public String toLogin(){
        return "login";
    }

In this way, we can easily create the front-end page, and we don't have to design the style and layout by ourselves. I still want to mention that it's enough to use it simply, but if you want to use it skillfully, you need to study more deeply.

3. Complete the login function

  • Create User entity class -- User java
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    
    private Integer id;
    private String username;
    private String password;
}
  • Create UserDao and its mapper mapping file -- UserDao java & UserDaoMapper. xml
@Mapper
@Repository
public interface UserDao {

    /**
     * User login function
     * @return
     */
    public User login(User user);


}
<?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.pikacho.dao.UserDao">
    <!-- public User login(User user)-->
    <select id="login" parameterType="User" resultType="User">
        select id, username, password
        from t_user
        where username = #{username} and password = #{password};
    </select>

  • Create UserService class and its implementation class -- UserService java & UserServiceImpl. java
public interface UserService {
    public User login(User user);
}
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    public UserDao userDao;

    @Override
    public User login(User user){
        return userDao.login(user);
    }
}
  • Using Shiro framework to realize login authentication function

Shiro framework can quickly realize login authentication and other security permission functions. Here is also a simple use. If you want to deeply understand the use, you need to consult its official documents.

UserRealm.java

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;


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

    // authentication
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token;

        User user = new User();
        user.setUsername(usernamePasswordToken.getUsername());
        user.setPassword(String.valueOf(usernamePasswordToken.getPassword()));
        // Query from database
        User userDB = userService.login(user);
        if(userDB == null){
            return null;
        }

        return new SimpleAuthenticationInfo(userDB, user.getPassword(), "");

    }
}

ShiroConfig.java

@Configuration
public class ShiroConfig {

    // Step 1: create UserRealm object
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    // Step 2: create the default security manager DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(
            @Qualifier("userRealm") UserRealm userRealm ){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    // Step 3: create ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(
            @Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        // Set up security manager
        bean.setSecurityManager(securityManager);
        /*
        *   anon: Access without authentication
            authc: You must authenticate before you can 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
         */

        // Intercept / file / *, which can only be viewed when logging in
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/file/*", "authc");
        bean.setFilterChainDefinitionMap(filterMap);

        // Jump to the page when no access permission is set
        bean.setLoginUrl("/login");
        return bean;
    }
}
  • Add login method in UserController class
    @PostMapping("login")
    public String login(User user, Model model){
        Subject subject = SecurityUtils.getSubject();
        // Encapsulate user information
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
        try{
            subject.login(token);
            Session session = subject.getSession();
            session.setAttribute("user", (User)subject.getPrincipal());
            // Go to file list page
            return "list";
        }catch (UnknownAccountException e){
            model.addAttribute("msg", "Wrong user name or password");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg", "Wrong user name or password");
            return "login";
        }
    }
  • Finally, add the package scanning annotation on the SpringbootFileuploadApplication class, otherwise mybatis cannot bind the interface to the xml configuration file
@SpringBootApplication
@MapperScan(basePackages = "com.pikacho.dao")
public class SpringbootFileuploadApplication {

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

}

The login function code has been developed. Now test whether the function is normal.  

Access project: http://localhost:8080/user/toLogin , a user was already created when the user table was created. User name: pikacho# password: 123456.

 

 4.2. Complete the registration function

1. Create a registration page

register.html

<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>register</title>
    <link rel="stylesheet" th:href="@{/css/layui.css}">

</head>
<body>
<div class="layui-container">
    <div class="layui-row" style="margin-top: 80px;">
        <div class="layui-col-lg4 layui-col-lg-offset4">
            <h1 style="margin:20px; text-align: center"> Please register </h1>
            <div class="layui-form-item">
                <p style="color: red; text-align: center" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
            </div>
            <form class="layui-form" th:action="@{/user/register}" method="post">
                <div class="layui-form-item">
                    <label class="layui-form-label">user name</label>
                    <div class="layui-input-block">
                        <input  class="layui-input" type="text" name="username" required>
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">password</label>
                    <div class="layui-input-block">
                        <input class="layui-input" type="password" name="password" required autocomplete="false">
                    </div>
                </div>
                <div class="layui-form-item">
                    <div class="layui-input-block">
                        <button class="layui-btn" lay-submit lay-filter="formDemo">Register now</button>
                        <button type="reset" class="layui-btn layui-btn-primary">Reset</button>
                    </div>
                </div>
            </form>
            <div style="float:right">
                <a th:href="@{/user/toLogin}">Go login</a>
            </div>
        </div>
    </div>
</div>
<script th:src="@{/layui.js}"></script>
<script>
    //Generally, it is written directly in a js file
    layui.use(['layer', 'form'], function(){
        var layer = layui.layer
            ,form = layui.form;
    });

</script>



</body>
</html>

2. Complete the registration function

  • Add register() in UserDao class and write mapper mapping file
    /**
     *
     * @param user
     */
    public void register(User user);
    <!-- register-->
    <insert id="register" parameterType="User">
        insert into t_user (username, password)
        values(#{username}, #{password});
    </insert>
  • Add a registration method in UserService class and implementation class
    /**
     *
     * @param user
     */
    public void register(User user);
    /**
     *
     * @param user
     */
    @Override
    public void register(User user){
        userDao.register(user);
    }
  • Add registration logic to the UserController class

Test the registration function and access the project: http://localhost:8080/user/toRegister  ; Add user pikacho2: 123456

 

 

4.3. Create a list page

Just create a list page to verify the login function. Now complete the list page.

list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>FileList</title>
    <link rel="stylesheet" th:href="@{/css/layui.css}">
</head>

<body>
<div class="layui-fluid">
    <nav class="layui-nav">
        <div class="layui-nav-item">
            <p class="layui-nav-title" style="font-size: larger">
                welcome:<span th:if="${session.user!=null}" th:text="${session.user.username}"/>
            </p>
        </div>
        <div class="layui-nav-item" style="float: right;">
            <button class="layui-btn">
                <a th:href="@{/user/logout}" style="font-size: larger; padding: 0px; color: white">login out</a>
            </button>
        </div>
        <div class="layui-nav-item" style="float: right; padding-right: 20px">
            <button type="button" class="layui-btn" id="fileUpload">
                Upload file
            </button>
        </div>
    </nav>

    <!-- File list-->
    <table id="fileList" lay-filter="fileTable"></table>

    <script type="text/html" id="optBar">
        <a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="download">download</a>
        <a class="layui-btn layui-btn-xs" lay-event="preview">preview</a>
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete">delete</a>
    </script>

</div>
<script th:src="@{/layui.js}" charset="utf-8"></script>

</body>
</html>

 4.4. Complete logout function

  • Add a logoff method in the UserController class
    /**
     * Registration function
     * @return
     */
    @GetMapping("logout")
    public String logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        // Note here: redirect: the actual request path of user / tologin http://localhost:8080/user/user/toLogin
        // So you need to use redirect:toLogin
        return "redirect:toLogin"; 
    }

5. Display, upload, delete and download of documents

5.1. Presentation of documents

  • Create file instance class -- userfile java
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Accessors(chain = true)
public class UserFile {
    private Integer id;
    private String fileName;
    private String ext;
    private String path;
    private long size;
    private String type;
    private Integer downloadCounts;
    private Date uploadTime;
    private Integer userId;
}
  • Create UserFileDao and its mapper mapping file
@Mapper
@Repository
public interface UserFileDao {

    /**
     * Obtain the user file list according to the user id
     * @param id
     * @param begin
     * @param offset
     * @return
     */
    public List<UserFile> queryByUserId(Integer id, Integer begin, int offset);


    /**
     * Obtain the total number of user files according to the user id
     * @param id
     * @return
     */
    public int queryFileCount(Integer id);
}
<?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.pikacho.dao.UserFileDao">
    <resultMap id="UserFileMap" type="UserFile">
        <!-- Only those whose column names and attribute names are inconsistent need to be mapped-->
        <id column="id" property="id"></id>
        <result column="file_name" property="fileName"></result>
        <result column="download_counts" property="downloadCounts"></result>
        <result column="upload_time" property="uploadTime"></result>
        <result column="user_id" property="userId"></result>
    </resultMap>

    <!-- According to user id Query file list-->
    <select id="queryByUserId" parameterType="Integer" resultMap="UserFileMap">
        select * from t_files
        where user_id = #{id}
        order by id
        limit #{begin}, #{offset};
    </select>
     <!-- According to user id Number of query files-->
    <select id="queryFileCount" parameterType="Integer" resultType="Integer">
        select count(*) from t_files
        where user_id = #{id};
    </select>
</mapper>
  • Create UserFileService class and its implementation class
public interface UserFileService {

    /**
     * Get the file list according to the user id
     * @param id
     * @param page
     * @param limit
     * @return
     */
    public List<UserFile> queryByUserId(Integer id, Integer page, Integer limit);

    /**
     * Get the number of files according to the user id
     * @param id
     * @return
     */
    public int queryFileCounts(Integer id);
}
@Service
public class UserFileServiceImpl implements UserFileService {
    @Autowired
    private UserFileDao userFileDao;

    /**
     * Get the file list according to the user id
     * @param id
     * @param page
     * @param limit
     * @return
     */
    @Override
    public List<UserFile> queryByUserId(Integer id, Integer page, Integer limit){
        // Page indicates the page number, and limit indicates how many rows of data are displayed on each page
        int begin = (page-1)*limit;   // This calculation method obtains the starting position
        int offset = limit;
        return userFileDao.queryByUserId(id, begin, limit);
    }

    /**
     * Get the number of files according to the user id
     * @param id
     * @return
     */
    @Override
    public int queryFileCounts(Integer id){
        return userFileDao.queryFileCounts(id);
    }
}
  • Create UserFileController class
@Controller
@RequestMapping("file")
public class UserFileController {
    @Autowired
    private UserFileService userFileService;

    /**
     * Return to file list
     * @param session
     * @param request
     * @return
     */
    @PostMapping("all")
    @ResponseBody
    public Map<String, Object> queryAllFile(HttpSession session, HttpServletRequest request){
        int page = Integer.parseInt(request.getParameter("page"));
        int limit = Integer.parseInt(request.getParameter("limit"));
        User user = (User) session.getAttribute("user");
        List<UserFile> files = userFileService.queryByUserId(user.getId(), page, limit);

        Map<String, Object> res = new HashMap<>();
        res.put("code", 0);
        res.put("count", userFileService.queryFileCounts(user.getId()));
        res.put("data", files);
        return res;
    }

}
  • Then on the list Add script to render table in HTML
        // Render table
        table.render({
            elem: '#fileList',
            height: 600,
            minWidth: 80,
            url: '/file/all',    // This must be / file/all. Before, file/all kept reporting errors and failed to access successfully
            parseData: function (res) {
                            return {
                                "code": res.code,
                                "msg": "",
                                "count": res.count,
                                "data": res.data
                            };
            },
            method: 'post',
            limit: 10,
            page: true,
            cols: [[
                {field:'id', title:'ID', sort:true, fixed:'left'},
                {field:'fileName', title:'file name'},
                {field:'ext', title:'file extension'},
                {field:'path', title:"Storage path"},
                {field:'size', title:'size'},
                {field:'type', title:"type"},
                {field:'downloadCounts', title:'amount of downloads'},
                {field:'uploadTime', title:'Upload time'},
                {tilte:'operation',align:'center', toolbar:'optBar', width:200, fixed:'right'}
            ]]
        });

5.2. File upload

  • Add the upload file method and mapper mapping file in the UserFileDao class
    /**
     * Upload file
     * @param userFile
     */
    public void save(UserFile userFile);
    <!-- Upload file-->
    <insert id="save" parameterType="UserFile" useGeneratedKeys="true" keyProperty="id">
        insert into t_files(file_name, ext, path, size, type, download_counts, upload_time, user_id)
        values(#{fileName}, #{ext}, #{path}, #{size}, #{type}, #{downloadCounts}, #{uploadTime}, #{userId});
    </insert>
  • Add methods in UserFileService class and UserFileServiceImpl class
    /**
     * Upload file
     * @param userFile
     */
    public void save(UserFile userFile);



    /**
     * Upload file
     * @param userFile
     */
    @Override
    public void save(UserFile userFile){
        userFile.setDownloadCounts(0).setUploadTime(new Date());
        userFileDao.save(userFile);
    }
  • Add the upload file interface in the UserFileController class
    @GetMapping("index")
    public String fileIndex(){
        return "list";
    }


    /**
     * Upload file
     * @param file
     * @param session
     * @return
     */
    @PostMapping("upload")
    @ResponseBody
    public Map<String, String> uploadFile(@RequestParam("file")MultipartFile file, HttpSession session){
        Map<String, String> res = new HashMap<>();
        try{
            User user = (User) session.getAttribute("user");
            String fileName = file.getOriginalFilename();
            String extension = FilenameUtils.getExtension(fileName);
            long size = file.getSize();
            String type = file.getContentType();
            // Generate directory based on date
            String localContainer = "/fileContainer";
            String uploadPath = ResourceUtils.getURL("classpath").getPath()+localContainer;
            String dateFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            File dateDirPath = new File(uploadPath+File.separator+dateFormat);
            if(!dateDirPath.exists()){
                dateDirPath.mkdirs();
            }

            file.transferTo(new File(dateDirPath, fileName));
            // Store file information in database
            UserFile userFile = new UserFile();
            userFile.setFileName(fileName)
                    .setExt('.'+extension)
                    .setPath(Paths.get(localContainer, dateFormat, fileName).toString())
                    .setSize(size)
                    .setType(type)
                    .setUserId(user.getId());

            userFileService.save(userFile);

            res.put("code", "0");
            res.put("msg", "Upload succeeded");
            res.put("url", "/file/index");

        }catch(IOException e){
            res.put("code", "-1");
            res.put("msg", "Upload failed");
            res.put("url", "/file/index");
        }
        return res;
    }

 

Here, the file is stored on my local disk, and the file table stores the storage path of the file on my disk.

5.3. File download

The development process is basically the same as above.

 // UserFiledao
   /**
     * Download File
     * @param id
     * @return
     */
    public UserFile queryByUserFileId(Integer id);

    /**
     * Update file downloads
     * @param userFile
     */
    public void update(UserFile userFile);


// UserFileService
    /**
     * Download File
     * @param id
     * @return
     */
    public UserFile queryByUserFileId(Integer id);

    /**
     * Download times of new files
     * @param userFile
     */
    public void update(UserFile userFile);

// UserFileServiceImpl
    /**
     * Download File
     * @param id
     * @return
     */
    @Override
    public UserFile queryByUserFileId(Integer id) {
        return userFileDao.queryByUserFileId(id);
    }

    /**
     * Download times of new files
     * @param userFile
     */
    @Override
    public void update(UserFile userFile) {
        userFileDao.update(userFile);
    }
    <!-- Download File-->
    <select id="queryByUserFileId" parameterType="Integer" resultMap="UserFileMap">
        select * from t_files where id = #{id};
    </select>
    <!-- Update file downloads-->
    <update id="update" parameterType="UserFile">
        update t_files set download_counts = #{downloadCounts} where id = #{id};
    </update>
    /**
     * Download File
     * @param id
     * @param response
     */
    @GetMapping("download/{id}")
    public void download(@PathVariable("id") Integer id, HttpServletResponse response){
        String openStyle = "attachment";
        try{
            getFile(openStyle, id, response);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * Update file downloads
     * @param openStyle
     * @param id
     * @param response
     * @throws Exception
     */
    public void getFile(String openStyle, Integer id, HttpServletResponse response) throws Exception {
        UserFile userFile = userFileService.queryByUserFileId(id);
        String realPath = ResourceUtils.getURL("classpath").getPath()+userFile.getPath();

        FileInputStream is = new FileInputStream(new File(realPath));
        // Attachment Download
        response.setHeader("content-disposition", openStyle+";filename=" + URLEncoder.encode(userFile.getFileName(), "UTF-8"));
        // Get the response output stream
        ServletOutputStream os = response.getOutputStream();
        // File copy
        IOUtils.copy(is, os);
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);

        if(openStyle.equals("attachment")){
            userFile.setDownloadCounts(userFile.getDownloadCounts()+1);
            userFileService.update(userFile);
        }
    }

list.html

        //Listening toolbar
        table.on('tool(fileTable)', function (obj) {
            var data = obj.data;
            if (obj.event === 'download') {
                window.open("/file/download/" + data.id);
                obj.update({
                    "downloadCounts": data.downloadCounts + 1
                });
            } else if (obj.event === 'delete') {
                layer.confirm('Are you sure you want to delete the file?', function (index) {
                    $.ajax({
                        url: "/file/delete/" + data.id,
                        type: "Get",
                        success: function (res) {
                            layer.msg(res.msg);
                            obj.del();
                        },
                        error: function (res) {
                            $.message.alert('msg', res.msg);
                        }
                    });
                    layer.close(index);
                });
            } else if (obj.event === 'preview') {
                
                layer.open({
                    type: 2,
                    skin: 'layui-layer-demo', //Style class name
                    title: 'File Preview',
                    closeBtn: 1, //Show close button
                    anim: 2,
                    area: ['893px', '600px'],
                    shadeClose: true, //Open mask close
                    content: '/file/preview/' + data.id
                });
            }
        });

 5.4. File deletion

The development process of file deletion is the same as above.

6. Complete the file preview function

  • Add preview method

    /**
     * File Preview
     * @param id
     * @param response
     * @throws IOException
     */
    @GetMapping("preview/{id}")
    public void preview(@PathVariable("id") Integer id, HttpServletResponse response) throws Exception {
        String openStyle = "inline";
        getFile(openStyle,id,response);
    }

At this point, this small project will be basically completed.

demo source addresshttps://github.com/picacho-pkq/SpringBoot-demo

demo download addresshttps://download.csdn.net/download/pikcacho_pkq/75146243

Topics: Java Spring Spring Boot intellij-idea