SpringBoot上傳下載文件及在線預覽


SpringBoot上傳下載文件及在線預覽

今天大概就說說如何使用SpringBoot進行上傳和下載以及在線預覽文件
本篇主要介紹上傳下載的功能,對於界面就簡單一點,大致如下:
在這里插入圖片描述

一、老規矩還是先看看小項目的目錄結構:

在這里插入圖片描述
在這里插入圖片描述

二、添加對應的pom依賴

<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.1</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>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

三、創建相應的配置

spring.application.name=files
server.port=8080
server.servlet.context-path=/files

spring.thymeleaf.cache=false
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.prefix=classpath:/templates/
spring.resources.static-locations=classpath:/templates/,classpath:/static/,file:${upload.dir}


spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/files?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root

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

#控制台進行打印日志
logging.level.root=info
logging.level.com.baizhi.dao=debug

#上傳和下載文件的路徑
upload.dir=D:/idea_project/java/files/target/classes/static

四、先准備登陸界面的工作

1、創建實體類

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain=true)
public class User {
    private Integer id;
    private String username;
    private String password;

}

2、創建對應的dao層

public interface UserDAO {

    User login(User user);
}

3、創建對應的mapper映射文件

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baizhi.dao.UserDAO">
    
    <!--login-->
    <select id="login" parameterType="User" resultType="com.baizhi.entity.User">
        select id,username,password
        from t_user
        where username=#{username}
        and password = #{password}
    </select>

</mapper>

4、創建業務層接口及實現類

public interface UserService {

    User login(User user);
}
@Service
@Transactional
public class UserServciceImpl  implements  UserService{

    @Autowired
    private UserDAO userDAO;

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public User login(User user) {
        return userDAO.login(user);
    }
}

5、創建控制器

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

    /**
     * 登錄方法
     */
    @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 "redirect:/index";
        }
    }

}

6、創建登陸界面

<!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="username"/> <br>
    password: <input type="text" name="password"/> <br>
    <input type="submit" value="登錄">
</form>

</body>
</html>

7、查看運行后對應的界面
4

五、進行主界面的操作

1、創建實體類

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain=true)
public class UserFile {
    private Integer id;
    private String oldFileName;
    private String newFileName;
    private String ext;
    private String path;
    private String size;
    private String type;
    private String isImg;
    private Integer downcounts;
    private Date uploadTime;
    private Integer userId; //用戶外鍵
}

2、創建對應的dao層

public interface UserFileDAO {

    //根據登錄用戶id獲取用戶的文件列表
    List<UserFile> findByUserId(Integer id);

    //保存用戶的文件記錄
    void save(UserFile userFile);

    //根據文件id獲取文件信息
    UserFile findById(String id);

    //根據id更新下載次數
    void update(UserFile userFile);

    //根據id刪除記錄
    void delete(String id);
}

3、創建dao層對應的mapper映射文件

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baizhi.dao.UserFileDAO">
    
    <!--根據用戶id查詢當前用戶的文件信息-->
    <select id="findByUserId" parameterType="Integer" resultType="com.baizhi.entity.UserFile">
        select  id,oldFileName,newFileName,ext,path,size,type,isImg,downcounts,uploadTime,userId
        from t_files
        where userId=#{id}
    </select>


    <!--保存文件信息-->
    <insert id="save" parameterType="com.baizhi.entity.UserFile" useGeneratedKeys="true" keyProperty="id">
      insert into t_files
        values (#{id},#{oldFileName},#{newFileName},
                #{ext},	#{path},#{size},#{type},
                #{isImg},#{downcounts},	#{uploadTime},#{userId})
    </insert>


    <!--根據id獲取文件信息-->
    <select id="findById" parameterType="String" resultType="com.baizhi.entity.UserFile">
        select id,oldFileName,newFileName,ext,path,size,type,isImg,downcounts,uploadTime,userId
        from t_files
        where id = #{id}
    </select>

    <!--更新下載次數-->
    <update id="update" parameterType="com.baizhi.entity.UserFile" >
        update t_files set downcounts=#{downcounts} where id=#{id}
    </update>

    <!--根據id刪除記錄-->
    <delete id="delete" parameterType="String">
        delete from t_files where id=#{id}
    </delete>

</mapper>

4、創建對應的業務層接口及實現類

public interface UserFileService {

    List<UserFile> findByUserId(Integer id);

    void save(UserFile userFile);

    UserFile findById(String id);

    void update(UserFile userFile);

    void delete(String id);
}

@Service
@Transactional
public class UserFileServiceImpl implements  UserFileService {

    @Autowired
    private UserFileDAO userFileDAO;

    @Override
    public List<UserFile> findByUserId(Integer id) {
        return userFileDAO.findByUserId(id);
    }

    @Override
    public void delete(String id) {
        userFileDAO.delete(id);
    }

    @Override
    public void update(UserFile userFile) {
        userFileDAO.update(userFile);
    }

    @Override
    public UserFile findById(String id) {
        return userFileDAO.findById(id);
    }

    @Override
    public void save(UserFile userFile) {
        //userFile.setIsImg()?  //是否是圖片 解決方案: 當類型中含有image時說明當前類型一定為圖片類型
        String isImg = userFile.getType().startsWith("image")?"是":"否";
        userFile.setIsImg(isImg);
        userFile.setDowncounts(0);
        userFile.setUploadTime(new Date());
        userFileDAO.save(userFile);
    }
}

5、創建控制器(重點)

  1. 上傳文件(且保存到i數據庫中)
@PostMapping("upload")
    public String upload(MultipartFile aaa, HttpSession session) throws IOException {
        //獲取上傳文件用戶id
        User user = (User) session.getAttribute("user");
        //獲取文件原始名稱
        String oldFileName = aaa.getOriginalFilename();
        //獲取文件后綴
        String extension = "." + FilenameUtils.getExtension(aaa.getOriginalFilename());
        //生成新的文件名稱
        String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + UUID.randomUUID().toString().replace("-", "") + extension;
        //文件大小
        Long size = aaa.getSize();
        //文件類型
        String type = aaa.getContentType();
        //處理根據日期生成目錄
        //String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static/files";
        String dateFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dateDirPath = uploadPath + "/files/" + dateFormat;
        File dateDir = new File(dateDirPath);
        if (!dateDir.exists()) dateDir.mkdirs();
        //處理文件上傳
        aaa.transferTo(new File(dateDir, newFileName));
        //將文件信息放入數據庫保存
        UserFile userFile = new UserFile();
        userFile.setOldFileName(oldFileName).setNewFileName(newFileName).setExt(extension).setSize(String.valueOf(size))
                .setType(type).setPath("/files/" + dateFormat).setUserId(user.getId());
        userFileService.save(userFile);
        return "redirect:/file/showAll";
    }
  1. 下載文件(在線預覽)
@GetMapping("download")
    public void download(String openStyle, String id, HttpServletResponse response) throws IOException {
        //獲取打開方式
        openStyle = openStyle == null ? "attachment" : openStyle;
        //獲取文件信息
        UserFile userFile = userFileService.findById(id);
        //點擊下載鏈接更新下載次數
        if ("attachment".equals(openStyle)) {
            userFile.setDowncounts(userFile.getDowncounts() + 1);
            userFileService.update(userFile);
        }
        //根據文件信息中文件名字 和 文件存儲路徑獲取文件輸入流
        String realpath = ResourceUtils.getURL("classpath:").getPath() + "/static" + userFile.getPath();
        //獲取文件輸入流
        FileInputStream is = new FileInputStream(new File(realpath, userFile.getNewFileName()));
        //附件下載
        response.setHeader("content-disposition", openStyle + ";fileName=" + URLEncoder.encode(userFile.getOldFileName(), "UTF-8"));
        //獲取響應輸出流
        ServletOutputStream os = response.getOutputStream();
        //文件拷貝
        IOUtils.copy(is, os);
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);
    }
  1. 展示所有文件信息
@GetMapping("showAll")
    public String findAll(HttpSession session, Model model) {
        //在登錄的session中獲取用戶的id
        User user = (User) session.getAttribute("user");

        //根據用戶id查詢有的文件信息
        List<UserFile> userFiles = userFileService.findByUserId(user.getId());
        //存入作用域中
        model.addAttribute("files", userFiles);
        return "showAll";
    }
  1. 刪除文件(及數據庫中的)
@GetMapping("delete")
    public String delete(String id) throws FileNotFoundException {

        //根據id查詢信息
        UserFile userFile = userFileService.findById(id);

        //刪除文件
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static" + userFile.getPath();
        File file = new File(realPath, userFile.getNewFileName());
        if(file.exists())file.delete();//立即刪除

        //刪除數據庫中記錄
        userFileService.delete(id);

        return "redirect:/file/showAll";
    }
  1. 返回當前的文件列表(json格式數據)
@GetMapping("findAllJSON")
    @ResponseBody
    public List<UserFile> findAllJSON(HttpSession session, Model model) {
        //在登錄的session中獲取用戶的id
        User user = (User) session.getAttribute("user");
        //根據用戶id查詢有的文件信息
        List<UserFile> userFiles = userFileService.findByUserId(user.getId());
        return userFiles;
    }

6、創建對應的界面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用戶文件列表頁面</title>
    <script th:src="@{/js/jquery-3.4.1.min.js}"></script>
    <script>
        $(function(){


            var time;
            $("#start").click(function(){
                console.log("開啟定時更新.........");
                time = setInterval(function () {
                    $.get("[[@{/file/findAllJSON}]]", function (res) {
                        //遍歷
                        $.each(res, 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.username}"/></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>
            <img th:if="${file.isImg}=='是'" style="width: 100px;height: 40px;" th:src="${#servletContext.contextPath}+${file.path}+'/'+${file.newFileName}" alt="">
            <span th:if="${file.isImg}!='是'" th:text="${file.isImg}"/>
        </td>
        <td th:id="${file.id}"><span th:text="${file.downcounts}"/></td>
        <td><span th:text="${#dates.format(file.uploadTime,'yyyy-MM-dd HH:mm:ss')}"/></td>
        <td>
            <a th:href="@{/file/download(id=${file.id})}">下載</a>
            <a th:href="@{/file/download(id=${file.id},openStyle='inline')}">在線打開</a>
            <a th:href="@{/file/delete(id=${file.id})}">刪除</a>
        </td>
    </tr>
</table>
<hr>

<h3>上傳文件:</h3>

<form th:action="@{/file/upload}" method="post" enctype="multipart/form-data">
    <input type="file" name="aaa"> <input type="submit" value="上傳文件">
</form>

</body>
</html>

六、創建攔截器

public class LoginInterceptor  implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        Object user = session.getAttribute("user");
        if(user!=null) return true;
        response.sendRedirect(request.getContextPath()+"/index");
        return false;
    }
}

七、創建過濾器

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {

    @Value("${upload.dir}")
    private String upload;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/file/**")
                .excludePathPatterns("/css/**")
                .excludePathPatterns("/js/**");//放行靜態資源 靜態資源被認為是一個控制器請求
    }

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**") //代表以什么樣的請求路徑訪問靜態資源
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/templates/")
                .addResourceLocations("file:"+upload);//本地資源路徑必須放在最上面

    }
}

八、進行測試

  1. 初始化
    6

  2. 上傳后
    7

  3. 下載
    8

  4. 在線預覽
    9

  5. 刪除
    變為初始化的樣子
    有需要源碼的可以聯系我!

還是要說說我的個人博客,希望大家多多訪問,謝謝!

天涯志


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM