Skip to content

Commit 59d1939

Browse files
committed
feat: improve split files
1 parent fb6b034 commit 59d1939

1 file changed

Lines changed: 115 additions & 10 deletions

File tree

TelegramDownloader/Data/FileService.cs

Lines changed: 115 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,11 @@ public async Task<List<BsonFileManagerModel>> ShareFile(string dbName, string bs
386386
await _db.subBytesToFolder(dbName, entry.ParentId, entry.Size);
387387
}
388388

389-
await _db.checkAndSetDirectoryHasChild(dbName, args.Files.FirstOrDefault().ParentId);
389+
var firstFile = args.Files.FirstOrDefault();
390+
if (firstFile != null)
391+
{
392+
await _db.checkAndSetDirectoryHasChild(dbName, firstFile.ParentId);
393+
}
390394
return await GetFilesPath(dbName, args.Path);
391395
}
392396

@@ -1903,11 +1907,25 @@ private async Task<List<ExpandoObject>> AddChildRecords(string id, string parent
19031907
if (path == "/")
19041908
{
19051909
List<BsonFileManagerModel> Data = collectionName == null ? await _db.getAllFiles(dbName) : await _db.getAllFiles(dbName, collectionName);
1906-
string ParentId = Data
1907-
.Where(x => string.IsNullOrEmpty(x.ParentId))
1908-
.Select(x => x.Id).First();
1909-
response.CWD = Data
1910-
.Where(x => string.IsNullOrEmpty(x.ParentId)).First().toFileManagerContent();
1910+
1911+
// Find root element (element with no ParentId)
1912+
var rootElement = Data.FirstOrDefault(x => string.IsNullOrEmpty(x.ParentId));
1913+
1914+
if (rootElement == null)
1915+
{
1916+
// No root element found, return empty response
1917+
response.CWD = new Syncfusion.Blazor.FileManager.FileManagerDirectoryContent
1918+
{
1919+
Name = "Root",
1920+
FilterPath = "/",
1921+
IsFile = false
1922+
};
1923+
response.Files = new List<Syncfusion.Blazor.FileManager.FileManagerDirectoryContent>();
1924+
return response;
1925+
}
1926+
1927+
string ParentId = rootElement.Id;
1928+
response.CWD = rootElement.toFileManagerContent();
19111929
response.Files = Data
19121930
.Where(x => x.ParentId == ParentId).Select(x => x.toFileManagerContent()).ToList();
19131931
}
@@ -2038,11 +2056,22 @@ private async Task SaveToFile(IBrowserFile file, string path)
20382056

20392057
private async Task<List<string>> splitFileStreamAsync(string path, string name, int splitSize)
20402058
{
2059+
var originalFileInfo = new System.IO.FileInfo(System.IO.Path.Combine(path, name));
2060+
long originalFileSize = originalFileInfo.Length;
2061+
20412062
_logger.LogInformation("Starting file split - FileName: {FileName}, SizeMB: {SizeMB:F2}, SplitSizeMB: {SplitSizeMB}",
2042-
name, new System.IO.FileInfo(System.IO.Path.Combine(path, name)).Length / (1024.0 * 1024.0), splitSize / (1024 * 1024));
2063+
name, originalFileSize / (1024.0 * 1024.0), splitSize / (1024 * 1024));
2064+
20432065
int _gb = TelegramService.splitSizeGB;
2066+
long partSize = (long)splitSize * _gb; // Size of each part in bytes
2067+
int expectedParts = (int)Math.Ceiling((double)originalFileSize / partSize);
2068+
2069+
// Check for existing split parts from a previous failed run
2070+
var existingParts = CheckExistingSplitParts(path, name, originalFileSize, partSize, expectedParts);
2071+
20442072
List<string> listPath = new List<string>();
20452073
byte[] buffer = new byte[splitSize];
2074+
20462075
using (FileStream fs = new FileStream(System.IO.Path.Combine(path, name), FileMode.Open, FileAccess.Read, FileShare.Read))
20472076
{
20482077
SplitModel sm = new SplitModel();
@@ -2051,13 +2080,33 @@ private async Task<List<string>> splitFileStreamAsync(string path, string name,
20512080
sm._transmitted = 0;
20522081
_tis.addToUploadList(sm);
20532082
int index = 1;
2083+
20542084
while (fs.Position < fs.Length)
20552085
{
20562086
string partPath = System.IO.Path.Combine(path, $"({index})" + name);
2087+
2088+
// Check if this part already exists and is valid
2089+
if (existingParts.TryGetValue(index, out var existingPartInfo) && existingPartInfo.isValid)
2090+
{
2091+
_logger.LogInformation("Reusing existing split part {PartNumber}/{TotalParts} - Size: {SizeMB:F2} MB",
2092+
index, expectedParts, existingPartInfo.size / (1024.0 * 1024.0));
2093+
2094+
// Skip this part in the source file
2095+
fs.Position += existingPartInfo.size;
2096+
listPath.Add(partPath);
2097+
sm.ProgressCallback(fs.Position, fs.Length);
2098+
index++;
2099+
continue;
2100+
}
2101+
2102+
// Delete existing invalid part if exists
20572103
if (File.Exists(partPath))
20582104
{
2105+
_logger.LogDebug("Deleting invalid existing part: {PartPath}", partPath);
20592106
File.Delete(partPath);
20602107
}
2108+
2109+
// Create new part
20612110
int gb = _gb;
20622111
while (fs.Position < fs.Length && gb > 0)
20632112
{
@@ -2070,16 +2119,72 @@ private async Task<List<string>> splitFileStreamAsync(string path, string name,
20702119
sm.ProgressCallback(fs.Position, fs.Length);
20712120
}
20722121

2073-
2074-
// await fs.CopyToAsync(fsPart, Convert.ToInt32(Math.Min(splitSize, fs.Length - fs.Position)));
20752122
listPath.Add(partPath);
20762123
index++;
20772124
}
20782125
}
2079-
_logger.LogInformation("File split completed - FileName: {FileName}, Parts: {PartsCount}", name, listPath.Count);
2126+
2127+
int reusedParts = existingParts.Count(p => p.Value.isValid);
2128+
_logger.LogInformation("File split completed - FileName: {FileName}, Parts: {PartsCount}, ReusedParts: {ReusedParts}",
2129+
name, listPath.Count, reusedParts);
20802130
return listPath;
20812131
}
20822132

2133+
/// <summary>
2134+
/// Checks for existing split parts from a previous failed run and validates their sizes
2135+
/// </summary>
2136+
private Dictionary<int, (long size, bool isValid)> CheckExistingSplitParts(string path, string name, long originalFileSize, long partSize, int expectedParts)
2137+
{
2138+
var existingParts = new Dictionary<int, (long size, bool isValid)>();
2139+
2140+
for (int i = 1; i <= expectedParts; i++)
2141+
{
2142+
string partPath = System.IO.Path.Combine(path, $"({i})" + name);
2143+
if (File.Exists(partPath))
2144+
{
2145+
var partInfo = new System.IO.FileInfo(partPath);
2146+
long actualSize = partInfo.Length;
2147+
2148+
// Calculate expected size for this part
2149+
long expectedSize;
2150+
if (i < expectedParts)
2151+
{
2152+
// Not the last part - should be full partSize
2153+
expectedSize = partSize;
2154+
}
2155+
else
2156+
{
2157+
// Last part - calculate remaining size
2158+
expectedSize = originalFileSize - (partSize * (expectedParts - 1));
2159+
}
2160+
2161+
bool isValid = actualSize == expectedSize;
2162+
2163+
existingParts[i] = (actualSize, isValid);
2164+
2165+
if (isValid)
2166+
{
2167+
_logger.LogDebug("Found valid existing part {PartNumber}/{TotalParts} - Size: {SizeMB:F2} MB",
2168+
i, expectedParts, actualSize / (1024.0 * 1024.0));
2169+
}
2170+
else
2171+
{
2172+
_logger.LogWarning("Found invalid existing part {PartNumber}/{TotalParts} - Expected: {ExpectedMB:F2} MB, Actual: {ActualMB:F2} MB",
2173+
i, expectedParts, expectedSize / (1024.0 * 1024.0), actualSize / (1024.0 * 1024.0));
2174+
}
2175+
}
2176+
}
2177+
2178+
if (existingParts.Any())
2179+
{
2180+
int validCount = existingParts.Count(p => p.Value.isValid);
2181+
_logger.LogInformation("Found {TotalExisting} existing split parts, {ValidCount} are valid and will be reused",
2182+
existingParts.Count, validCount);
2183+
}
2184+
2185+
return existingParts;
2186+
}
2187+
20832188
private async Task mergeFileStreamAsync(List<string> pathList, string destName)
20842189
{
20852190
_logger.LogInformation("Starting file merge - DestName: {DestName}, PartsCount: {PartsCount}", destName, pathList.Count);

0 commit comments

Comments
 (0)