文件上传与下载是 Web 服务最基础也最高频的能力,从网盘、CMS 到 OSS 网关几乎无处不在。实现逻辑无非两件事:把 multipart/form-data 里的文件流式存到磁盘;再把磁盘上的文件送回客户端。
本文用同一个"上传文件到服务器、再把它下载回去"的小服务为例,展示 wastnet 在上传与下载场景下的 API 设计。
场景
一个文件服务器,两个接口:
POST /upload:接收 multipart/form-data 上传,把文件流式保存到磁盘,返回带下载链接的页面;
GET /download?name=xxx:把服务器上的文件作为附件返回给客户端(文件不存在返回 404)。
wastnet 实现:上手即可用
引入依赖
<dependency>
<groupId>io.github.wycst</groupId>
<artifactId>wastnet-core</artifactId>
<version>1.0.1</version>
</dependency>
零第三方依赖,仅依赖 JDK 本身。
上传:几行核心逻辑
// 判断是否为 multipart 请求
if (request.isMultipart()) {
// 遍历所有表单字段
for (String fieldName : request.getMultipartFieldNames()) {
MultipartField field = request.getMultipartField(fieldName);
if (field.isFile()) {
// 文件字段:流式落盘,不占内存
field.transferTo(new File(UPLOAD_DIR, field.getFileName()));
} else {
// 普通表单字段
// 文本场景直接 getDataAsString();需要字节或自定义编码时用 getData() 更自由
String value = field.getDataAsString();
}
}
}
三个 API 全部面向业务:isFile() 判断字段类型、transferTo() 流式落盘(大文件不经过内存)、getData() 读取普通字段字节。文件内容按流处理,上传 1GB 的文件也不会有内存压力。
下载:一行 sendFile
response.header("Content-Disposition", "attachment; filename=\"" + safeName + "\"");
response.sendFile(file);
sendFile 自动处理 Content-Type、Content-Length 与文件流发送,大文件走零拷贝路径,无需手写任何 IO。
完整可运行示例
以上逻辑对应 wastnet 测试模块中的真实示例,可直接运行:
wastnet-test/src/main/java/io/github/wycst/wastnet/examples/http/FileUploadDownloadTest.java
启动后用 curl 验证:
# 上传一个文件
curl -k -X POST -F "file=@/path/to/large.zip" https://localhost:8080/upload
# 把它下载回来
curl -k -O -J "https://localhost:8080/download?name=large.zip"
完整示例
以上片段省略了部分骨架代码(如 HTTPServer 构建、监听器注册),完整可运行版本见 wastnet-test/src/main/java/io/github/wycst/wastnet/examples/http/FileUploadDownloadTest.java。
wastnet 基于 Apache 2.0 协议完全开源、免费使用。
相关链接