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