一、环境准备
<?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 http://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.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.edward</groupId>
<artifactId>myfileserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>myfileserver</name>
<description>mongodbfileserver project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/de.flapdoodle.embed/de.flapdoodle.embed.mongo
这个是采用内嵌MongoDB服务器需要的依赖
-->
<!--<dependency>-->
<!--<groupId>de.flapdoodle.embed</groupId>-->
<!--<artifactId>de.flapdoodle.embed.mongo</artifactId>-->
<!--</dependency>-->
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、项目结构
本项目采用springboot构件的
三、配置
application.properties配置文件
server.address=localhost
server.port=8081
# Thymeleaf
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false
spring.thymeleaf.mode=HTML5
# limit upload file size
spring.servlet.multipart.max-file-size=1024KB
spring.servlet.multipart.max-request-size=1024KB
# independent MongoDB server 如果采用内嵌MongoDB服务器把这个注释掉
spring.data.mongodb.uri=mongodb://localhost:27017/test
安全配置类 SecurityConfig.java文件
/**
1. Spring Security 配置类.
*/
@Configuration
@EnableWebMvc
public class SecurityConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*") ; // 允许跨域请求
}
}
三、后台编码
1.domain层 File.java
/**
1. File 文档类.
*/
@Document
public class File {
@Id // 主键
private String id;
private String name; // 文件名称
private String contentType; // 文件类型
private long size;
private Date uploadDate;
private String md5;
private Binary content; // 文件内容
private String path; // 文件路径
//get set 方法
protected File() {
}
public File(String name, String contentType, long size,Binary content) {
this.name = name;
this.contentType = contentType;
this.size = size;
this.uploadDate = new Date();
this.content = content;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
File fileInfo = (File) object;
return java.util.Objects.equals(size, fileInfo.size)
&& java.util.Objects.equals(name, fileInfo.name)
&& java.util.Objects.equals(contentType, fileInfo.contentType)
&& java.util.Objects.equals(uploadDate, fileInfo.uploadDate)
&& java.util.Objects.equals(md5, fileInfo.md5)
&& java.util.Objects.equals(id, fileInfo.id);
}
@Override
public int hashCode() {
return java.util.Objects.hash(name, contentType, size, uploadDate, md5, id);
}
}
- 存储库FileRepository.java
/**
* File 存储库.
*/
public interface FileRepository extends MongoRepository<File, String> {
}
3.服务接口及实现类
FileService.java
/**
* File 服务接口.
*/
public interface FileService {
/**
* 保存文件
*/
File saveFile(File file);
/**
* 删除文件
*/
void removeFile(String id);
/**
* 根据id获取文件
*/
Optional<File> getFileById(String id);
/**
* 分页查询,按上传时间降序
* @return
*/
List<File> listFilesByPage(int pageIndex, int pageSize);
}
FileServiceImpl.java
/**
* File 服务.
*/
@Service
public class FileServiceImpl implements FileService {
@Autowired
public FileRepository fileRepository;
@Override
public File saveFile(File file) {
return fileRepository.save(file);
}
@Override
public void removeFile(String id) {
fileRepository.deleteById(id);
}
@Override
public Optional<File> getFileById(String id) {
return fileRepository.findById(id);
}
@Override
public List<File> listFilesByPage(int pageIndex, int pageSize) {
Page<File> page = null;
List<File> list = null;
Sort sort = new Sort(Direction.DESC,"uploadDate");
Pageable pageable = PageRequest.of(pageIndex, pageSize, sort);
page = fileRepository.findAll(pageable);
list = page.getContent();
return list;
}
}
4.控制层、API资源层
FileController.java
@CrossOrigin(origins = "*", maxAge = 3600) // 允许所有域名访问
@Controller
public class FileController {
@Autowired
private FileService fileService;
@Value("${server.address}")
private String serverAddress;
@Value("${server.port}")
private String serverPort;
@RequestMapping(value = "/")
public String index(Model model) {
// 展示最新二十条数据
model.addAttribute("files", fileService.listFilesByPage(0, 20));
return "index";
}
/**
* 分页查询文件
*/
@GetMapping("files/{pageIndex}/{pageSize}")
@ResponseBody
public List<File> listFilesByPage(@PathVariable int pageIndex, @PathVariable int pageSize) {
return fileService.listFilesByPage(pageIndex, pageSize);
}
/**
* 获取文件片信息
*/
@GetMapping("files/{id}")
@ResponseBody
public ResponseEntity<Object> serveFile(@PathVariable String id) throws UnsupportedEncodingException {
Optional<File> file = fileService.getFileById(id);
if (file.isPresent()) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=" + new String(file.get().getName().getBytes("utf-8"),"ISO-8859-1"))
.header(HttpHeaders.CONTENT_TYPE, "application/octet-stream")
.header(HttpHeaders.CONTENT_LENGTH, file.get().getSize() + "").header("Connection", "close")
.body(file.get().getContent().getData());
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not fount");
}
}
/**
* 在线显示文件
*/
@GetMapping("/view/{id}")
@ResponseBody
public ResponseEntity<Object> serveFileOnline(@PathVariable String id) {
Optional<File> file = fileService.getFileById(id);
if (file.isPresent()) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "fileName=\"" + file.get().getName() + "\"")
.header(HttpHeaders.CONTENT_TYPE, file.get().getContentType())
.header(HttpHeaders.CONTENT_LENGTH, file.get().getSize() + "").header("Connection", "close")
.body(file.get().getContent().getData());
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not fount");
}
}
/**
* 上传
*/
@PostMapping("/")
public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
try {
File f = new File(file.getOriginalFilename(), file.getContentType(), file.getSize(),
new Binary(file.getBytes()));
f.setMd5(MD5Util.getMD5(file.getInputStream()));
fileService.saveFile(f);
System.out.println(f);
} catch (IOException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
redirectAttributes.addFlashAttribute("message", "Your " + file.getOriginalFilename() + " is wrong!");
return "redirect:/";
}
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
return "redirect:/";
}
/**
* 上传接口
*/
@PostMapping("/upload")
@ResponseBody
public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
File returnFile = null;
try {
File f = new File(file.getOriginalFilename(), file.getContentType(), file.getSize(),
new Binary(file.getBytes()));
f.setMd5(MD5Util.getMD5(file.getInputStream()));
returnFile = fileService.saveFile(f);
String path = "//" + serverAddress + ":" + serverPort + "/view/" + returnFile.getId();
return ResponseEntity.status(HttpStatus.OK).body(path);
} catch (IOException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());
}
}
/**
* 删除文件
*/
@DeleteMapping("/{id}")
@ResponseBody
public ResponseEntity<String> deleteFile(@PathVariable String id) {
try {
fileService.removeFile(id);
return ResponseEntity.status(HttpStatus.OK).body("DELETE Success!");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
}
}
5.工具类 MD5Util.java
/**
* MD5 工具类.
*/
public class MD5Util {
/**
* 获取该输入流的MD5值
*/
public static String getMD5(InputStream is) throws NoSuchAlgorithmException, IOException {
StringBuffer md5 = new StringBuffer();
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = is.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
};
byte[] mdbytes = md.digest();
// convert the byte to hex format
for (int i = 0; i < mdbytes.length; i++) {
md5.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
return md5.toString();
}
}
四、前台页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<h1>File server</h1>
<a href="/">首页</a>
<div th:if="${message}">
<h2 th:text="${message}"/>
</div>
<div>
<form method="POST" enctype="multipart/form-data" action="/">
<table>
<tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr>
<tr><td></td><td><input type="submit" value="Upload" /></td></tr>
</table>
</form>
</div>
<div>
<table border="1">
<thead>
<tr>
<td>Name</td>
<td>ID</td>
<td>contentType</td>
<td>size</td>
<td>uploadDate</td>
<td>md5</td>
</tr>
</thead>
<tbody>
<tr th:if="${files.size()} eq 0">
<td colspan="3">没有文件信息!!</td>
</tr>
<tr th:each="file : ${files}">
<td><a th:href="'files/'+${file.id}" th:text="${file.name}" /></td>
<td th:text="${file.id}" ></td>
<td th:text="${file.contentType}" ></td>
<td th:text="${file.size}" ></td>
<td th:text="${file.uploadDate}" ></td>
<td th:text="${file.md5}" ></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
版权声明:本文为victoyr原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。