在移动应用开发和测试过程中,经常需要从本地服务器获取最新的 APK 安装包。本文将详细介绍如何使用 Java 构建一个能够搜索本地最新 APK 文件并通过 HTTP 请求提供下载服务的应用。
功能概述
我们要实现的应用需要具备以下核心功能:
- 递归搜索本地目录,查找所有 APK 文件
- 根据文件修改时间找出最新的 APK 文件
- 通过 HTTP 请求响应机制,将 APK 文件返回给前端
- 处理各种异常情况,确保服务稳定可靠
下面让我们一步步实现这些功能。
实现本地 APK 文件搜索
首先,我们需要一个能够扫描本地目录并找出最新 APK 文件的工具类。以下是实现代码:
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class ApkFileFinder { private static final String APK_EXTENSION = ".apk"; /** * 查找指定目录下最新的APK文件 * @param searchDir 搜索目录 * @return 最新APK文件的Path,未找到时返回null * @throws IOException 文件操作异常 */ public static Path findLatestApk(String searchDir) throws IOException { try (Stream<Path> walk = Files.walk(Paths.get(searchDir))) { List<Path> apkFiles = walk .filter(Files::isRegularFile) .filter(p -> p.getFileName().toString().toLowerCase().endsWith(APK_EXTENSION)) .collect(Collectors.toList()); if (apkFiles.isEmpty()) { return null; } return apkFiles.stream() .max(Comparator.comparingLong(p -> { try { return Files.getLastModifiedTime(p).toMillis(); } catch (IOException e) { return 0; } })) .orElse(null); } } }
这个工具类的核心是使用 Java NIO 的 Files.walk 方法递归遍历目录,结合 Stream API 筛选出 APK 文件,并根据文件的最后修改时间排序找出最新的文件。
创建 HTTP 下载服务
接下来,我们需要将找到的 APK 文件通过 HTTP 服务提供给前端。这里使用 Servlet 技术实现:
import java.io.IOException; import java.net.URLEncoder; import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/downloadLatestApk") public class ApkDownloadServlet extends HttpServlet { private static final String APK_SEARCH_DIR = "C:/apps/"; private static final String DEFAULT_CHARSET = "UTF-8"; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { // 设置响应编码 resp.setCharacterEncoding(DEFAULT_CHARSET); // 查找最新APK Path latestApk = ApkFileFinder.findLatestApk(APK_SEARCH_DIR); if (latestApk == null) { resp.sendError(HttpServletResponse.SC_NOT_FOUND, "未找到APK文件"); return; } // 设置响应头 String fileName = generateDownloadFileName(latestApk); resp.setContentType("application/vnd.android.package-archive"); resp.setHeader("Content-Disposition", "attachment; filename="" + URLEncoder.encode(fileName, DEFAULT_CHARSET) + """); resp.setHeader("Content-Length", String.valueOf(Files.size(latestApk))); // 输出文件内容 Files.copy(latestApk, resp.getOutputStream()); } catch (Exception e) { resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "下载过程中发生错误: " + e.getMessage()); } } private String generateDownloadFileName(Path sourcePath) { String baseName = sourcePath.getFileName().toString(); int extIndex = baseName.lastIndexOf('.'); String nameWithoutExt = extIndex > 0 ? baseName.substring(0, extIndex) : baseName; String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")); return nameWithoutExt + "_" + timestamp + ".apk"; } }
这个 Servlet 类主要做了以下工作:
-
使用 @WebServlet 注解将 Servlet 映射到 /downloadLatestApk 路径
-
在 doGet 方法中调用之前的文件搜索工具类获取最新 APK
-
设置 HTTP 响应头,包括内容类型、文件名和文件大小
-
将 APK 文件内容直接写入响应输出流
-
处理可能出现的异常情况并返回适当的 HTTP 状态码
部署与使用
要使用这个服务,需要完成以下步骤:
1. 环境准备
确保你已经安装:
- JDK 8 或更高版本
- Apache Tomcat 或其他 Servlet 容器
- Maven(可选,用于项目构建)
2. 创建 Web 项目
可以使用 Maven 创建一个简单的 Web 项目,添加以下依赖:
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> </dependencies>
3. 部署应用
将上述代码放入项目中,打包为 WAR 文件并部署到 Tomcat 的 webapps 目录下。
4. 配置搜索路径
修改代码中的 APK_SEARCH_DIR 常量,指向你的 APK 文件存放目录。
5. 访问服务
启动 Tomcat 后,访问以下 URL 即可触发 APK 下载:
http://localhost:8080/your-context-root/downloadLatestApk
示例与测试
假设你的 APK 文件存放在 C:/apps/ 目录下,结构如下:
C:/apps/ ├── app-v1.0.apk (修改时间: 2023-01-01 10:00) ├── app-v1.1.apk (修改时间: 2023-01-10 14:30) └── app-v1.2.apk (修改时间: 2023-01-15 09:15)
当你访问下载 URL 时,系统会自动选择最新的 app-v1.2.apk 文件,并以类似 "app-v1.2_20230115_103045.apk" 的文件名提供下载,其中时间戳部分是下载时生成的。
常见问题与解决方案
- 文件找不到错误
- 检查 APK_SEARCH_DIR 路径是否正确
- 确保 Tomcat 用户有访问该目录的权限
- 中文文件名乱码
- 确认代码中使用了 URLEncoder 处理文件名
- 确保 Servlet 容器配置为使用 UTF-8 编码
- 大文件下载问题
-
对于非常大的 APK 文件,考虑使用缓冲流或异步下载
总结
通过本文介绍的方法,你可以轻松实现一个本地 APK 文件搜索和 HTTP 下载服务。这个服务可以方便开发团队内部共享最新的应用安装包,提高测试和部署效率。