ActFramework – 如何用不到 70 行 Java 代码撸一个文件上传管理服务
- 2020 年 3 月 9 日
- 笔记
ActFramework 1.8.32 发布了(欢迎围观新闻), 这个版本中我们优化了 storage service 部分, 文件上传管理代码变得更加简洁. 下面我们来看看如果用不到 70 行 Java 代码来实现一个完整的上传文件管理服务.
定义上传文件对象:
@Entity(name="file") public class UploadFile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer id; public String description; /** * key to fetch the file from {@link org.osgl.storage.IStorageService} */ public String ssKey; }
文件上传服务
@UrlContext("fm") public class FileManager extends Controller.Util { @Inject private IStorageService ss; // 注入存储服务实例 @Inject JPADao<Integer, UploadFile> dao; // 注入 Dao /** * 文件上传服务页面 - 使用模板生成页面 */ @GetAction public void home() { Iterable<UploadFile> files = dao.findAll(); renderTemplate("/fm.html", files); } /** * 上传一个文件 * @param file 上传文件 */ @PostAction("upload") public void upload(ISObject file, String description) { String key = ss.getKey(); // 生成一个 unique 的 key ss.put(key, file); // 将文件存入存储服务 UploadFile uf = new UploadFile(); // 生成一个上传数据记录 uf.ssKey = key; uf.description = description; dao.save(uf); // 将上传数据记录存入本地数据库 redirect("/fm"); // 重定向到文件上传服务页面 } /** * 下载文件 * @param __path URL 路径里在 download 之后的部分, 这是获得文件存储的 key * @return 从存储系统中获得的文件. */ @GetAction("download/...") // 注意 ... 的写法, 这样可以将 `...` 部分放入 `__path` 中 public ISObject download(String __path) { return ss.get(__path); } /** * 删除一个上传文件 */ @DeleteAction("{uploadFile}") public void delete(@DbBind @NotNull UploadFile uploadFile) { ss.remove(uploadFile.ssKey); // 从存储系统中删除 dao.delete(uploadFile); // 从本地数据库中删除 } }
文件上传服务页面代码
<!DOCTYPE html> <html lang="en"> <head> <title>File Manager Home</title> <style> label { display: inline-block; width: 200px; text-align: right; padding: 5px 15px; } input { padding: 5px 15px; } #submit { margin-left: 249px; } </style> <script src="/~/asset/js/jquery.js"></script> <script src="/~/asset/js/jquery.ext.js"></script> </head> <body> <h1>Simple File Manager</h1> <h3>Upload new file</h3> <form method="post" action="/fm/upload" enctype="multipart/form-data"> <div> <label for="description">Description</label> <input type="text" name="description" id="description" style="margin-left: 15px"> </div> <div> <label for="file">Select file</label> <input id="file" name="file" type="file"> </div> <div> <button id="submit" type="submit">Submit</button> </div> </form> @args Iterable<demo.act.fm.UploadFile> files @if(files) { <h3>Upload file list</h3> <ul id="file-list"> @for(files) { <li> <a href="/fm/download/@_.ssKey" target="_blank">@_.description</a> <button type="button" class="btn_delete" data-id="@_.id">Delete</button> </li> } </ul> <script> $('.btn_delete').on('click', function() { $.delete('/fm/' + $(this).data('id'), function(){ window.location.reload() }) }) </script> } </body> </html>
配置存储服务
锐利的看官可能要问了, 上面代码里面的 private IStorageService ss
是个什么东东. 这个是由 osgl-storage 库提供的存储服务. 开发人员可以根据需要对该实例进行配置
下面是在本地文件系统上的配置:
ss.impl=act.storage.FileSystemStoragePlugin ss.storage.fs.home.dir=upload # 这将会在项目目录中创建一个 upload 子目录
osgl-storage 的一个优势是你可以随时将文件存储从本地文件系统切换到云端存储, 比如下面就是一个基于 AWS S3 bucket 的配置:
ss.impl=act.storage.S3StoragePlugin ss.storage.s3.keyId={key id} ss.storage.s3.keySecret={key secret} ss.storage.s3.bucket={s3 bucket name} ss.storage.s3.get.noGet=false ss.storage.s3.defStorageClass=standard ss.storage.s3.maxErrorRetry=5 ss.storage.s3.tcpKeepAlive=true ss.storage.s3.maxConnection=30
osgl-storage 还支持更多的云端服务, 包括 Azure 的 Blob 系统和七牛云.
运行演示:

点击 A PDF file

总结
本文讲述了如何在 ActFramework 中用短短的不到 70 行 Java 代码来实现一个文件上传服务管理.
看官: 口说无凭, 你说不到 70 行就不到 70 行啊?
老码农: 元芳, 上证据:

@红薯 完整项目已经提交 Gitee: https://gitee.com/greenlaw110/file-manager