factory i/o下载_Java编程第48讲——文件下载服务器的实现

7270647cfbd848dae8991451b2e987da.png

前面的文章《Java编程第42讲——使用SpringBoot实现静态网站》中,用SpringBoot实现了一个古诗词网。其实,在这个服务器的static目录中放入其他的文件,譬如readme.txt文件,通过浏览器可以直接查看,通过迅雷,也可以直接下载:

de559fc312ee68e3a0252811491ed19c.png
c1bf683d6cbaf42686eb6f9c6923c263.png
e89b4af5455fb9cdba337acf554f1c89.png
8e794f8fbfd2978954d23d3f0690391d.png
8074a6f1ec5b9af329bcf19eed3d3713.png
8640172b8a2b8f3d6d1e8c264e4c3f24.png
02e9d5fec0ef498f638c052d2161a56b.png

但是,把这个功能当成文件下载功能,就太粗糙了。个人认为,即使最简单的文件下载服务器,也至少具备下面两个要点:

(1)通过浏览器输入要下载的资源的URL后,浏览器可以保存附件;

(2)软件工程师可以根据需要,添加控制文件下载权限的代码。

下面,我们基于SpringBoot,使用IDEA开发工具,开发一个简单的文件下载服务器吧。

第1步:使用IDEA创建一个空项目fc_prj,然后在fc_prj项目中添加一个SpringBoot项目file_center,加入Lombok、Spring Web、Spring Data JPA、MySQL Driver四个依赖。操作完成后项目视图如下:

b05cd8b2acc255e983bb1ccf4db81eae.png

第2步:在mysql中执行下面的SQL语句,建立本项目使用的数据库db_fc:

create database db_fc default character set utf8;
c4484fd9e976049c77e53f69302d226b.png

第3步:在db_fc数据库中建立t_user表,用于进行权限控制,为了让程序显得简单,这里t_user表只包含用户名、密码、备注三个字段,建立t_user表的SQL语句如下:

use db_fc;create table t_user(    user_name varchar(32) primary key not null,    password varchar(32) not null,    comment varchar(64))engine=InnoDB default charset=utf8;
a16f12ee8d5354fc9963c040842661fd.png

第4步:我们在t_user表中插入张三、李四、王五三个用户的信息,SQL语句如下:

insert into t_user(user_name, password, comment) values('zhangsan', 'zhang', '用户张三');insert into t_user(user_name, password, comment) values('lisa', 'li', '用户李四');insert into t_user(user_name, password, comment) values('wangwu', 'wang', '用户王五');commit;
1414843785359f2b02a49e0f35cebd17.png

第5步:在db_fc数据库中建立t_file表,用于记录可以下载的文件信息,该表有文件标识符、文件完整路径两个字段,建立t_file表的SQL语句如下:

use db_fc;create table t_file(    file_id varchar(32) primary key not null,    file_path varchar(512) not null)engine=InnoDB default charset=utf8;
3af237f473f89a75a2ab75ca5be941d0.png

第6步:我们向t_file表中插入一些可以下载的文件信息,SQL语句如下:

insert into t_file(file_id, file_path) values('flower', '/root/files/flower.jpg');insert into t_file(file_id, file_path) values('hello.txt', '/root/files/hello.txt');commit;
2b5b2ce1b3884ab5e76ad09851c613a5.png

第7步:新建entity包;

4e357e630827812b4d76f8a64126bf33.png

第8步:在entity包中建立UserEntity类,一个UserEntity实例对应t_user表的一条记录。UserEntity的代码如下:

package com.flying.file_center.entity;import lombok.Data;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;@Data@Table(name="t_user")@Entitypublic class UserEntity {    @Id    private String userName;    private String password;    private String comment;}

第9步:在entity包中建立FileEntity类,一个FileEntity实例对应t_file表的一条记录。FileEntity的代码如下:

package com.flying.file_center.entity;import lombok.Data;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;@Data@Table(name="t_file")@Entitypublic class FileEntity {    @Id    private String fileId;    private String filePath;}

第10步:新建repository包;

1b2efddaab32bec6236302ccb628abe3.png

第11步:在repository包中建立UserRepository接口,用于操作t_user表,代码如下:

package com.flying.file_center.repository;import com.flying.file_center.entity.UserEntity;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.jpa.repository.JpaSpecificationExecutor;import org.springframework.stereotype.Repository;import java.util.List;@Repositorypublic interface UserRepository  extends JpaRepository, JpaSpecificationExecutor {    List queryUserEntitiesByUserNameAndPassword(String userName, String password);}

第12步:在repository包中建立FileRepository接口,用于操作t_file表,代码如下:

package com.flying.file_center.repository;import com.flying.file_center.entity.FileEntity;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.jpa.repository.JpaSpecificationExecutor;import org.springframework.stereotype.Repository;import java.util.List;@Repositorypublic interface FileRepository extends JpaRepository, JpaSpecificationExecutor {    List queryFileEntitiesByFileId(String fileId);}

第13步:新建controller包和service包:

5719a658fed547d2c87d5f7ad46415e7.png

第14步:在service包中建立FileService类,用于实现处理HTTP下载请求,代码如下:

package com.flying.file_center.service;import com.flying.file_center.entity.FileEntity;import com.flying.file_center.entity.UserEntity;import com.flying.file_center.repository.FileRepository;import com.flying.file_center.repository.UserRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletResponse;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.OutputStream;import java.util.List;@Servicepublic class FileService {    @Autowired    private FileRepository fileRepository;    @Autowired    private UserRepository userRepository;    public void download(String userName, String password, String fileId, HttpServletResponse httpServletResponse){        List userEntityList = userRepository.queryUserEntitiesByUserNameAndPassword(userName, password);        if (userEntityList.size() == 0){            httpServletResponse.setStatus(401);            return;        }        List fileEntityList = fileRepository.queryFileEntitiesByFileId(fileId);        if (fileEntityList.size() == 0){            httpServletResponse.setStatus(404);            return;        }                File file = new File(fileEntityList.get(0).getFilePath());        if (file.exists()) {            httpServletResponse.setContentType("application/force-download");            httpServletResponse.addHeader("Content-Disposition",                    "attachment;fileName=" + fileEntityList.get(0).getFileId());            byte[] bytesBuffer = new byte[1024];            try (FileInputStream fis = new FileInputStream(file);                 BufferedInputStream bis = new BufferedInputStream(fis);            ) {                OutputStream outputStream = httpServletResponse.getOutputStream();                int i = bis.read(bytesBuffer);                while (i != -1) {                    outputStream.write(bytesBuffer, 0, i);                    i = bis.read(bytesBuffer);                }            } catch (Exception e) {                e.printStackTrace();            }        }else{            httpServletResponse.setStatus(404);        }    }}

第15步:在controller包中建立FileController类,用于接收来自浏览器或其他客户端的HTTP下载请求,代码如下:

package com.flying.file_center.controller;import com.flying.file_center.service.FileService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;@RestController@Slf4jpublic class FileController {    @Autowired    private HttpServletResponse httpServletResponse;        @Autowired    private FileService fileService;    @GetMapping("/download/{userName}/{password}/{fileId}")    public void download(@PathVariable(value="userName") String userName,                         @PathVariable(value="password") String password,                         @PathVariable(value="fileId") String fileId){        fileService.download(userName, password, fileId, httpServletResponse);    }}

第16步:修改application.properties文件,加入服务器的配置信息,这里只配置服务器使用的端口和数据库连接信息,application.properties文件的内容如下:

server.port=9201spring.datasource.url=jdbc:mysql://127.0.0.1/db_fc?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=truespring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.max-idle=10spring.datasource.max-wait=10000spring.datasource.min-idle=5spring.datasource.initial-size=5

第17步:修改pom.xml文件,加入编译和打包的信息,修改后的pom.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>4.0.0org.springframework.boot        spring-boot-starter-parent        2.3.4.RELEASEcom.flying    file_center    1.0.1file_centerDemo project for Spring Boot1.8org.springframework.boot            spring-boot-starter-data-jpa        org.springframework.boot            spring-boot-starter-web        mysql            mysql-connector-java            runtimeorg.projectlombok            lombok            trueorg.springframework.boot            spring-boot-starter-test            testorg.junit.vintage                    junit-vintage-engine                fcorg.apache.maven.plugins                maven-jar-plugin                *.properties*.txt*.xml                            true                                                        fc_lib/falsecom.flying.file_center.FileCenterApplication./resources/${project.build.directory}org.apache.maven.plugins                maven-dependency-plugin                copy-dependenciespackagecopy-dependencies                                ${project.build.directory}/fc_lib/                                            maven-resources-plugin                copy-resourcespackagecopy-resourcessrc/main/resources${project.build.directory}/resources

第18步:在IDEA的Terminal窗口输入mvn clean package -DskipTests命令,完成程序的编译与打包,得到fc.jar和相关的文件:

206e38fd16b3d56551ce635c85c50208.png
deb80b07428b43a10f395d3c7e813d14.png
f836bd4f4109133d483f59f5ec212a16.png

第19步:将fc.jar文件和依赖的库文件和资源文件拷贝到Linux运行环境:

3ff960ee500ca7fdc195957f22747e13.png

第20步:在Linux的/root目录中新建files目录,然后向该目录中传入两个文件flower.jpg和hello.txt:

933ef312161c37e98c94091578dad58e.png

第21步:执行java -jar fc.jar命令,启动文件下载服务器:

cac7771d895c6da8a6136bd23b1a2e9f.png

第22步:当我们在浏览器中输入http://:9201/download/zhangsan/zhang/flower时,浏览器会自动下载文件flower.jpg,并且生成的文件名是我们指定的FileId,也就是flower:

8460cbae71a0793c35e0928e6a02b765.png

第23步:当我们在浏览器中故意输错用户名或密码,例如输入http://:9201/download/zhangsan/zhang2/flower时,将会得到HTTP 401错误:

1b475300904b1febf5cc0e0929fae45d.png

第23步:当我们在浏览器中故意输错文件ID,例如输入http://:9201/download/zhangsan/zhang/flower.jpg时,将会得到HTTP 404错误:

9e66f12f6ff18778d64c7e9425ad2315.png

开发完成!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值