I heard that wechat search “Java fish” will change strong oh!
This article is in Java Server, which contains my complete series of Java articles, can be read for study or interview
(1) Overview
File upload and download has always been a system is the most commonly used is the most basic function point, just recently the company’s project useful to this function, so I use SpringBoot also wrote a simplified version, has realized the file upload and download function.
(2) Create a project
Start by creating a SpringBoot project and then introduce the dependencies, which are more dependent because of the database operations involved.
2.1 Dependency Import
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<! -- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<! -- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</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>
</dependency>
Copy the code
2.2 Interface general return class writing
Write a generic return body for the interface, which I wrote about in a previous blog post and now use directly:
public enum ResponseCode {
// System module
SUCCESS(0."Operation successful"),
ERROR(1."Operation failed"),
SERVER_ERROR(500."Server exception"),
// Universal module 1xxxx
ILLEGAL_ARGUMENT(10000."Invalid parameter"),
REPETITIVE_OPERATION(10001."Do not repeat operation"),
ACCESS_LIMIT(10002."Too many requests. Please try again later."),
MAIL_SEND_SUCCESS(10003."Email sent successfully"),
// User module 2xxxx
NEED_LOGIN(20001."Login invalid"),
USERNAME_OR_PASSWORD_EMPTY(20002."User name or password cannot be empty"),
USERNAME_OR_PASSWORD_WRONG(20003."Wrong username or password"),
USER_NOT_EXISTS(20004."User does not exist"),
WRONG_PASSWORD(20005."Password error"),
// File module 3xxxx
FILE_EMPTY(30001."File cannot be empty."),
FILE_NAME_EMPTY(30002."File name cannot be empty"),
FILE_MAX_SIZE(30003."File size out"),; ResponseCode(Integer code, String msg) {this.code = code;
this.msg = msg;
}
private Integer code;
private String msg;
public Integer getCode(a) {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg(a) {
return msg;
}
public void setMsg(String msg) {
this.msg = msg; }}Copy the code
Return to the body:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {
private int code;
private String message;
private Object data;
}
Copy the code
2.3 Configuring the configuration classes to resolve cross-domain problems
There are several approaches to cross-domain resolution in SpringBoot, one of which is selected here
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/ * *")
.allowedOrigins("*")
.allowedMethods("POST"."GET"."PUT"."OPTIONS"."DELETE")
.maxAge(3600)
.allowCredentials(true); }}Copy the code
At this point, the basic configuration of the project is complete, and it is time to implement the functionality.
(3) Upload and download files
3.1 create a table
First create a table to record the file path, name, suffix, and so on:
CREATE TABLE `file` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`filePath` varchar(255) DEFAULT NULL,
`fileName` varchar(255) DEFAULT NULL,
`fileSuffix` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
Copy the code
3.2 Writing entity classes
Write a file object corresponding to a field in the database:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode
public class Files implements Serializable {
private static final long serialVersionUID=1L;
/** * File storage path */
private String filePath;
/** * File name */
private String fileName;
/** * File name extension */
private String fileSuffix;
}
Copy the code
3.3 configuration application. The properties
In the configuration file, configure the service port, database connection mode, and file saving path:
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/test7? serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.mapper-locations=classpath:mapper/*.xml
file.save-path=E:/temp/files
Copy the code
3.4 write a Controller
Create a new class called FileController, which is used to write the interface. The code for the file upload and download interface has been commented out. Spring provides a MultipartFile class, which is used to receive files from the front end.
@RestController
@RequestMapping("/api")
public class FileController {
@Autowired
private FileService fileService;
@RequestMapping(value = "/upload",method = RequestMethod.POST)
public Result upLoadFiles(MultipartFile multipartFile){
if (multipartFile.isEmpty()){
return new Result(ResponseCode.FILE_EMPTY.getCode(),ResponseCode.FILE_EMPTY.getMsg(),null);
}
return fileService.upLoadFiles(multipartFile);
}
@RequestMapping(value = "/download/{id}",method = RequestMethod.GET)
public void downloadFiles(@PathVariable("id") String id, HttpServletRequest request, HttpServletResponse response){
OutputStream outputStream=null;
InputStream inputStream=null;
BufferedInputStream bufferedInputStream=null;
byte[] bytes=new byte[1024];
Files files = fileService.getFileById(id);
String fileName = files.getFileName();
// Get the output stream
try {
response.setHeader("Content-Disposition"."attachment; filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
response.setContentType("application/force-download");
inputStream=fileService.getFileInputStream(files);
bufferedInputStream=new BufferedInputStream(inputStream);
outputStream = response.getOutputStream();
int i=bufferedInputStream.read(bytes);
while(i! = -1){
outputStream.write(bytes,0,i); i=bufferedInputStream.read(bytes); }}catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(inputStream! =null){
inputStream.close();
}
if(outputStream! =null){
outputStream.close();
}
if(bufferedInputStream! =null){ bufferedInputStream.close(); }}catch(IOException e) { e.printStackTrace(); }}}}Copy the code
FileService interface and fileServiceImpl implementation classes are required to implement all services in the service:
public interface FileService {
/** * File upload interface *@param file
* @return* /
Result upLoadFiles(MultipartFile file);
/** * Get file by id *@param id
* @return* /
Files getFileById(String id);
/** * Get data stream * by id@param files
* @return* /
InputStream getFileInputStream(Files files);
}
Copy the code
FileServiceImpl implementation class:
@Service
public class FileServiceImpl implements FileService {
@Value("${file.save-path}")
private String savePath;
@Autowired
private FileMapper fileMapper;
@Override
public Result upLoadFiles(MultipartFile file) {
// Set the maximum number of files that can be uploaded. Here, 1024*1024*2=2M
long MAX_SIZE=2097152L;
// Get the name of the file to upload
String fileName=file.getOriginalFilename();
// If the name is empty, an error with an empty file name is returned
if (StringUtils.isEmpty(fileName)){
return new Result(ResponseCode.FILE_NAME_EMPTY.getCode(),ResponseCode.FILE_NAME_EMPTY.getMsg(),null);
}
// If the file exceeds the maximum value, an error is returned that exceeds the maximum value that can be uploaded
if (file.getSize()>MAX_SIZE){
return new Result(ResponseCode.FILE_MAX_SIZE.getCode(),ResponseCode.FILE_MAX_SIZE.getMsg(),null);
}
// Get the suffix name
String suffixName = fileName.contains(".")? fileName.substring(fileName.lastIndexOf(".")) : null;
// Rename the saved file according to the timestamp
String newName = System.currentTimeMillis() + suffixName;
File newFile=new File(savePath,newName);
if(! newFile.getParentFile().exists()){ newFile.getParentFile().mkdirs(); }try {
// File write
file.transferTo(newFile);
} catch (IOException e) {
e.printStackTrace();
}
// Write the information about these files to the database
Files files=new Files(newFile.getPath(),fileName,suffixName);
fileMapper.insertFile(files);
return new Result(ResponseCode.SUCCESS.getCode(),ResponseCode.SUCCESS.getMsg(),"Data uploaded successfully");
}
// Get file information by id
@Override
public Files getFileById(String id) {
Files files = fileMapper.selectFileById(id);
return files;
}
// Convert the file to InputStream
@Override
public InputStream getFileInputStream(Files files) {
File file=new File(files.getFilePath());
try {
return new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null; }}Copy the code
3.5 Operations on the Database
Create FileMapper interface to write data to database (mybatis)
@Mapper
@Repository
public interface FileMapper {
/** * Insert data information into the database *@param files
*/
void insertFile(Files files);
/** * Get file by id *@param id
* @return* /
Files selectFileById(String id);
}
Copy the code
Write the corresponding XML file
<! DOCTYPEmapper
PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javayz.fileuploadanddownload.mapper.FileMapper">
<insert id="insertFile" parameterType="com.javayz.fileuploadanddownload.entity.Files">
insert into file(filepath,filename,filesuffix) values(#{filePath},#{fileName},#{fileSuffix});
</insert>
<select id="selectFileById" parameterType="string" resultType="com.javayz.fileuploadanddownload.entity.Files">
select * from file where id=#{id};
</select>
</mapper>
Copy the code
Code has been uploaded to Github, welcome to: github
(4) Test
To get the project up and running, first test file uploads, uploading a file directly through Postman
Click send to get the return value of the successful operation. We can see the file in the path set by ourselves, and also the information of the file exists in the database:
The next test file to download, because is a get request, directly in the browser visit: http://localhost:8080/api/download/4 can call to download.