blob: dcbee69c963c5eabe4bb03692548a39828cf036d [file] [log] [blame]
22301102bc6da0a2025-06-02 17:47:29 +08001package com.pt.service;
2
3import com.pt.entity.TorrentMeta;
4import com.pt.repository.TorrentMetaRepository;
5import com.pt.utils.BencodeUtils;
6import org.springframework.beans.factory.annotation.Autowired;
7import org.springframework.stereotype.Service;
8
9import java.io.*;
10import java.security.MessageDigest;
11import java.time.LocalDateTime;
12import java.util.LinkedHashMap;
13import java.util.Map;
14
15@Service
16public class TorrentService {
17
18 // Tracker 服务器的 announce 地址
19 private static final String ANNOUNCE_URL = "http://localhost:8080/announce";
20 private static final int PIECE_LENGTH = 256 * 1024;
21
22 @Autowired
23 private TorrentMetaRepository torrentMetaRepository;
24
25 public byte[] generateTorrentBytes(String sourceFilePath) throws Exception {
26 File sourceFile = new File(sourceFilePath);
27
28 // 构造 info 字典
29 Map<String, Object> infoDict = new LinkedHashMap<>();
30 infoDict.put("name", sourceFile.getName());
31 infoDict.put("length", sourceFile.length());
32 infoDict.put("piece length", PIECE_LENGTH);
33 infoDict.put("pieces", calcPiecesHashes(sourceFile));
34
35 // 构造完整 torrent 字典
36 Map<String, Object> torrentDict = new LinkedHashMap<>();
37 torrentDict.put("announce", ANNOUNCE_URL);
38 torrentDict.put("info", infoDict);
39
40 // 编码成种子数据字节数组
41 byte[] bencodedTorrent = BencodeUtils.encode(torrentDict);
42
43 // 计算 info_hash 并保存到数据库(如果需要的话)
44 MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
45 byte[] infoEncoded = BencodeUtils.encode(infoDict);
46 sha1.update(infoEncoded);
47 String infoHash = bytesToHex(sha1.digest());
48
49 TorrentMeta meta = new TorrentMeta();
50 meta.setFilename(sourceFile.getName());
51 meta.setInfoHash(infoHash);
52 meta.setSize(sourceFile.length());
53 meta.setUploadTime(LocalDateTime.now());
54 torrentMetaRepository.save(meta);
55
56 return bencodedTorrent;
57 }
58
59
60 private byte[] calcPiecesHashes(File file) throws Exception {
61 MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
62 try (InputStream fis = new FileInputStream(file)) {
63 byte[] buffer = new byte[PIECE_LENGTH];
64 ByteArrayOutputStream piecesBuffer = new ByteArrayOutputStream();
65
66 int read;
67 while ((read = fis.read(buffer)) > 0) {
68 sha1.reset();
69 sha1.update(buffer, 0, read);
70 piecesBuffer.write(sha1.digest());
71 }
72 return piecesBuffer.toByteArray();
73 }
74 }
75
76 private String bytesToHex(byte[] bytes) {
77 StringBuilder sb = new StringBuilder();
78 for (byte b : bytes) {
79 sb.append(String.format("%02x", b));
80 }
81 return sb.toString();
82 }
83}