Java解析磁力链(Magnet URI)的完整指南

磁力链(Magnet URI)是一种常见的P2P文件共享链接格式。下面我将详细介绍如何在Java中解析磁力链的各个组成部分。
1. 理解磁力链的结构
一个典型的磁力链接(Magnet URI)格式如下:
magnet:?xt=urn:btih:哈希值&dn=显示名称&tr=Tracker地址&...
磁力链接是一种基于内容寻址的超链接协议,主要用于P2P文件共享。其组成部分通过"&"符号连接,每个参数都有特定的功能:
- xt (eXact Topic):
- 核心标识符,使用URN(统一资源名称)格式
- 最常见的格式是"urn:btih:"后接40个字符的SHA-1哈希值
- 示例:xt=urn:btih:9C1E05D471B855A4A1F1E1F7A5B5E3E7E8E9EA0
- dn (Display Name):
- 人类可读的文件名显示
- 支持多语言,需进行URL编码
- 示例:dn=Ubuntu+20.04+Desktop.iso
- tr (Tracker):
- 可选的Tracker服务器地址
- 可包含多个Tracker,每个用"&tr="分隔
- 示例:tr=udp://tracker.opentrackr.org:1337/announce
- xl (eXact Length):
- 精确的文件大小(字节)
- 有助于预先分配磁盘空间
- 示例:xl=2796554240
- as (Acceptable Source):
- 指定可接受的备用源URI
- 可以是HTTP/FTP等其他下载源
- 示例:as=http://mirror.example.com/ubuntu.iso
- xs (eXact Source):
- 直接资源链接
- 通常用于补充P2P下载
- 示例:xs=http://cdn.example.com/file.ext
附加说明:
- 参数顺序不影响功能
- 所有非ASCII字符需进行百分比编码
- 现代客户端还支持ws (WebSocket)等新参数
- 哈希算法除了SHA-1,也可支持MD5、SHA-256等
实际应用示例: magnet:?xt=urn:btih:9C1E05D471B855A4A1F1E1F7A5B5E3E7E8E9EA0&dn=Ubuntu+20.04&tr=udp://tracker.opentrackr.org:1337&xl=2796554240&as=http://releases.ubuntu.com/20.04/ubuntu-20.04-desktop-amd64.iso
2. Java解析磁力链的核心代码
2.1 使用URI类解析
import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; public class MagnetParser { public static Map<String, String> parseMagnetLink(String magnetLink) throws URISyntaxException { Map<String, String> params = new HashMap<>(); URI uri = new URI(magnetLink); String query = uri.getRawQuery(); if (query != null) { String[] pairs = query.split("&"); for (String pair : pairs) { int idx = pair.indexOf("="); String key = idx > 0 ? pair.substring(0, idx) : pair; String value = idx > 0 && pair.length() > idx + 1 ? pair.substring(idx + 1) : ""; params.put(key, value); } } return params; } } 2.2 使用URLDecoder处理编码
import java.io.UnsupportedEncodingException; import java.net.URLDecoder; // 在上述parseMagnetLink方法中添加解码处理 try { value = URLDecoder.decode(value, "UTF-8"); } catch (UnsupportedEncodingException e) { // 保持原始值 } 3. 完整示例代码
import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; import java.util.HashMap; import java.util.Map; public class MagnetParserDemo { public static void main(String[] args) { String magnetLink = "magnet:?xt=urn:btih:1a2b3c4d5e6f7g8h9i0j&dn=example+file.mp4&tr=udp%3A%2F%2Ftracker.example.com%3A6969"; try { Map<String, String> result = parseMagnetLink(magnetLink); System.out.println("磁力链解析结果:"); System.out.println("哈希值: " + extractHash(result.get("xt"))); System.out.println("文件名: " + result.get("dn")); System.out.println("Tracker: " + result.get("tr")); System.out.println("文件大小: " + (result.containsKey("xl") ? formatSize(result.get("xl")) : "未知")); } catch (URISyntaxException e) { System.err.println("无效的磁力链格式: " + e.getMessage()); } } private static String extractHash(String xt) { if (xt == null) return null; // 从xt值中提取哈希部分,如"urn:btih:1a2b3c..." return xt.substring(xt.lastIndexOf(':') + 1); } private static String formatSize(String xl) { try { long bytes = Long.parseLong(xl); if (bytes < 1024) return bytes + " B"; int exp = (int) (Math.log(bytes) / Math.log(1024)); String pre = "KMGTPE".charAt(exp-1) + "i"; return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre); } catch (NumberFormatException e) { return xl + " B"; } } public static Map<String, String> parseMagnetLink(String magnetLink) throws URISyntaxException { // 同上文parseMagnetLink方法实现 // ... } } 4. 实际应用场景
- BT客户端开发:解析磁力链获取文件哈希和Tracker地址
- 下载管理器:识别磁力链并启动相应下载协议
- 资源搜索工具:从磁力链中提取关键信息建立索引
- 文件校验工具:通过btih哈希验证文件完整性
5. 注意事项
磁力链(Magnet URI)中的参数排列具有灵活性,其核心特征包括:
- 参数顺序可变性
- 各参数间用"&"符号连接,但排列顺序不影响功能
- 例如"magnet:?xt=...&dn=..."和"magnet:?dn=...&xt=..."是等效的
- 这种设计增强了协议的兼容性
- 参数重复机制
- 关键参数允许重复出现,特别是Tracker服务器地址
- 典型应用场景:多个备用Tracker时形如"tr=udp://tracker1&tr=udp://tracker2"
- 客户端应支持解析所有重复参数值
- 编码处理要求
- 参数值可能包含特殊字符,需遵循RFC 3986的百分号编码规则
- 常见需要解码的字符:空格(%20)、冒号(%3A)、斜杠(%2F)等
- 实现时必须先解码再使用参数值
- 哈希值多样性
- 主标识符(xt参数)支持多种哈希类型:
- 40字符的SHA-1哈希(URN格式:urn:sha1:)
- 32字符的Base32编码(URN格式:urn:btih:)
- 部分客户端还支持MD5等其他哈希算法
- 示例对比:
- SHA-1:urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C
- Base32:urn:btih:QJZ5VWQ6KJNHVZ5FWAH5Q5PX6KJNHVZ5
- 扩展性考虑
- 协议保留未知参数的处理机制
- 新参数应使用x.前缀(如x.foo=bar)
- 客户端应忽略无法识别的参数而不报错
6. 扩展功能
如果需要更复杂的解析,可以考虑:
- 处理多个Tracker地址
List<String> trackers = new ArrayList<>(); for (Map.Entry<String, String> entry : params.entrySet()) { if (entry.getKey().startsWith("tr")) { trackers.add(entry.getValue()); } } - 解析Web种子(ws参数)
- 处理Peer地址(pe参数)
- 支持更多哈希类型(MD5, SHA-256等)
通过以上方法,您可以轻松地在Java应用程序中解析和处理磁力链信息。