下面我将提供一个完整的Java实现方案,用于在本地文件系统中搜索APK文件,并通过HTTP服务提供下载功能。
![图片[1]_Java实现本地APK文件搜索与HTTP下载服务_知途无界](https://zhituwujie.com/wp-content/uploads/2025/07/d2b5ca33bd20250711104838.png)
1. 项目结构
APKDownloadService/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/apkservice/
│ │ │ ├── ApkFile.java // APK文件模型
│ │ │ ├── ApkSearcher.java // APK文件搜索器
│ │ │ ├── DownloadServer.java // HTTP下载服务器
│ │ │ └── Main.java // 主程序入口
│ │ └── resources/
│ └── test/
│ └── java/ // 测试代码
└── pom.xml // Maven配置文件
2. 实现代码
2.1 APK文件模型 (ApkFile.java)
package com.example.apkservice;
import java.io.File;
public class ApkFile {
private String name;
private String packageName;
private String version;
private long size;
private File file;
private String path;
public ApkFile(File file) {
this.file = file;
this.name = file.getName();
this.path = file.getAbsolutePath();
this.size = file.length();
// 实际应用中可以从APK中解析包名和版本号
this.packageName = "unknown";
this.version = "unknown";
}
// Getters and Setters
public String getName() { return name; }
public String getPackageName() { return packageName; }
public String getVersion() { return version; }
public long getSize() { return size; }
public File getFile() { return file; }
public String getPath() { return path; }
}
2.2 APK文件搜索器 (ApkSearcher.java)
package com.example.apkservice;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
public class ApkSearcher {
private static final String APK_EXTENSION = ".apk";
public List<ApkFile> searchApkFiles(String rootPath) {
List<ApkFile> apkFiles = new ArrayList<>();
File root = new File(rootPath);
if (!root.exists() || !root.isDirectory()) {
throw new IllegalArgumentException("Invalid root path: " + rootPath);
}
searchApkFilesRecursive(root, apkFiles);
return apkFiles;
}
private void searchApkFilesRecursive(File directory, List<ApkFile> apkFiles) {
File[] files = directory.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() ||
(file.isFile() && file.getName().toLowerCase().endsWith(APK_EXTENSION));
}
});
if (files == null) return;
for (File file : files) {
if (file.isDirectory()) {
searchApkFilesRecursive(file, apkFiles);
} else {
apkFiles.add(new ApkFile(file));
}
}
}
}
2.3 HTTP下载服务器 (DownloadServer.java)
package com.example.apkservice;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
public class DownloadServer {
private HttpServer server;
private List<ApkFile> apkFiles;
private int port;
public DownloadServer(List<ApkFile> apkFiles, int port) {
this.apkFiles = apkFiles;
this.port = port;
}
public void start() throws IOException {
server = HttpServer.create(new InetSocketAddress(port), 0);
server.createContext("/", new RootHandler());
server.createContext("/download", new DownloadHandler());
server.createContext("/list", new ListHandler());
server.setExecutor(Executors.newCachedThreadPool());
server.start();
System.out.println("Server started on port " + port);
}
public void stop() {
if (server != null) {
server.stop(0);
System.out.println("Server stopped");
}
}
private class RootHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
String response = "<html><body>" +
"<h1>APK Download Service</h1>" +
"<p><a href='/list'>View APK List</a></p>" +
"</body></html>";
exchange.sendResponseHeaders(200, response.length());
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
private class ListHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append("<html><body>");
sb.append("<h1>Available APK Files</h1>");
sb.append("<table border='1'>");
sb.append("<tr><th>Name</th><th>Size</th><th>Action</th></tr>");
for (ApkFile apk : apkFiles) {
sb.append("<tr>");
sb.append("<td>").append(apk.getName()).append("</td>");
sb.append("<td>").append(formatFileSize(apk.getSize())).append("</td>");
sb.append("<td><a href='/download?file=")
.append(apk.getPath().replace("\\", "/"))
.append("'>Download</a></td>");
sb.append("</tr>");
}
sb.append("</table>");
sb.append("</body></html>");
exchange.getResponseHeaders().set("Content-Type", "text/html");
exchange.sendResponseHeaders(200, sb.length());
OutputStream os = exchange.getResponseBody();
os.write(sb.toString().getBytes());
os.close();
}
private String formatFileSize(long size) {
if (size < 1024) return size + " B";
if (size < 1024 * 1024) return (size / 1024) + " KB";
return (size / (1024 * 1024)) + " MB";
}
}
private class DownloadHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
Map<String, String> params = queryToMap(exchange.getRequestURI().getQuery());
String filePath = params.get("file");
if (filePath == null || filePath.isEmpty()) {
String response = "File parameter is missing";
exchange.sendResponseHeaders(400, response.length());
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
return;
}
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
String response = "File not found: " + filePath;
exchange.sendResponseHeaders(404, response.length());
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
return;
}
// Set headers
exchange.getResponseHeaders().set("Content-Type", "application/vnd.android.package-archive");
exchange.getResponseHeaders().set("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
exchange.sendResponseHeaders(200, file.length());
// Stream file
try (FileInputStream fis = new FileInputStream(file);
OutputStream os = exchange.getResponseBody()) {
byte[] buffer = new byte[4096];
int count;
while ((count = fis.read(buffer)) != -1) {
os.write(buffer, 0, count);
}
}
}
private Map<String, String> queryToMap(String query) {
Map<String, String> result = new HashMap<>();
if (query == null) return result;
for (String param : query.split("&")) {
String[] pair = param.split("=");
if (pair.length > 1) {
result.put(pair[0], pair[1]);
} else {
result.put(pair[0], "");
}
}
return result;
}
}
}
2.4 主程序入口 (Main.java)
package com.example.apkservice;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("APK File Search and Download Service");
System.out.print("Enter root directory to search for APK files: ");
String rootPath = scanner.nextLine();
System.out.print("Enter server port (default 8080): ");
String portStr = scanner.nextLine();
int port = portStr.isEmpty() ? 8080 : Integer.parseInt(portStr);
try {
// Search for APK files
ApkSearcher searcher = new ApkSearcher();
List<ApkFile> apkFiles = searcher.searchApkFiles(rootPath);
System.out.println("Found " + apkFiles.size() + " APK files:");
for (ApkFile apk : apkFiles) {
System.out.println("- " + apk.getName() + " (" + apk.getSize() + " bytes)");
}
// Start HTTP server
DownloadServer server = new DownloadServer(apkFiles, port);
server.start();
System.out.println("Press ENTER to stop the server...");
scanner.nextLine();
server.stop();
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
} finally {
scanner.close();
}
}
}
3. Maven依赖配置 (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>apk-download-service</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- For APK parsing (optional) -->
<dependency>
<groupId>net.dongliu</groupId>
<artifactId>apk-parser</artifactId>
<version>2.6.10</version>
</dependency>
</dependencies>
</project>
4. 使用说明
- 编译并运行程序:
mvn clean package
java -jar target/apk-download-service-1.0-SNAPSHOT.jar
- 按照提示输入要搜索APK文件的根目录和服务器端口(默认8080)
- 程序会扫描指定目录下的所有APK文件并启动HTTP服务器
- 访问以下URL:
http://localhost:8080/– 服务主页http://localhost:8080/list– 查看APK文件列表http://localhost:8080/download?file=/path/to/file.apk– 下载指定APK文件
- 按Enter键停止服务器
5. 扩展功能建议
- APK元数据解析:使用
apk-parser库从APK文件中提取包名、版本号等元数据 - 安全认证:添加基本的HTTP认证保护下载服务
- 缓存机制:对频繁下载的文件实现缓存
- 日志记录:记录下载请求和错误
- 多线程优化:优化大文件下载时的性能
- REST API:提供JSON格式的API接口供其他程序调用
这个实现提供了一个完整的本地APK文件搜索和HTTP下载服务,可以根据实际需求进行进一步定制和扩展。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END
























暂无评论内容