应用程序中免不了要上传下载文件,实现方式由简单到复杂有很多种:
- 最简单的,文件上传后服务端程序将文件写到服务器上一个指定的目录
- 稍微复杂一点,我们需要和应用服务器分开的单独文件服务器
- 再复杂一点,需要用到分布式文件存储。文件在多个文件服务器之间做冗余备份
使用单独文件服务器
各种方案没有好坏之分,要根据系统场景看是否适用。
第一种方式非常简单,适用于一些访问量小,存储文件不多的应用程序。
多数应用系统其实第二种方案就可以了。
很复杂的采用第三种。
选择独立文件服务要求
- 有基本的权限控制。不做控制的话,一个爬虫就连锅端了。
- 使用单独文件服务器。上传下载的压力由文件服务器承担
- API支持,方便Java程序进行文件存储
Filebrowser + OkHttp 方案
不用自己造轮子。Filebrowser + OkHttp是一个不错的方案。
- Filebrowser满足上面文件服务的所有要求。Filebrower提供了基于Http的接口让客户端上传下载文件。
- Java发送Http请求有很多可选方案。JDK自带的库,apache 的 http component, 以及OkHttp开源库。相比之下 OkHttp比较好,主要是API封装得不错,简单易懂,功能全面,效率也不错。实际上在Android程序中OkHttp得到了广泛使用。发送Http请求的任务就靠他了。
实施
Filebrowser安装
按照 Filebrowser的官方安装文档进行安装。
安装完成之后,在浏览器中打开UI, 确认安装正确
写文件服务器工具
此工具的作用是把controller收到的multipart file存储到文件服务器上去。
文件存储助手代码
/**
* 文件上传
* @param bytes 文件数据
* @param storedFileName 文件存储名称
* @return 上传是否成功
* @throws IOException
*/
public boolean upload(byte[] bytes, String storedFileName) throws IOException {
OkHttpClient httpClient = new OkHttpClient();
MediaType mediaType = MediaType.Companion.parse("application/octet-stream");
RequestBody requestBody = RequestBody.Companion.create(bytes, mediaType);
Request request = new Request.Builder()
.url(fileServerUrl + "/api/resource/" + storedFileName)
.post(requestBody)
.build();
try(Response response = httpClient.newCall(request).execute()){
return response.isSuccessful();
}
}
Controller代码
@PostMapping("/upload/boardImg")
public ApiResp uploadBoardImg(MultipartFile file) throws IOException {
String storedFileName = FOLDER_NAME_BOARD + SEPARATOR + FileUtils.genUniqueName(file.getOriginalFilename());
if(fileStorageClient.upload(file.getBytes(), storedFileName)){
return ApiResp.ok(storedFileName);
} else {
return ApiResp.failed("图片上传失败");
}
}
这样文件就通过应用服务器上传到单独的文件服务器去了。
查看文件
每个上传的文件在文件服务器上都有一个相对路径。应用系统中只需要存相对路径即可。查看的时候把文件服务器下载API地址和相对路径拼接起来就可以拿到文件了。具体形式为:
http://文件服务器IP/api/download/ + 相对路径
至此,拥有单独文件服务器的文件上传下载就实现了。
Next
下一篇文章,我将介绍如何进一步做权限控制。
网友评论