Skip to content

Commit

Permalink
FTP.UploadFiles checksum and retry
Browse files Browse the repository at this point in the history
  • Loading branch information
Riku Virtanen committed Oct 17, 2024
1 parent 58ed8ea commit b950362
Show file tree
Hide file tree
Showing 12 changed files with 323 additions and 65 deletions.
5 changes: 5 additions & 0 deletions Frends.FTP.UploadFiles/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## [1.2.0]
### Added
- Added check for file checksum and size.
- Added retry attempts parameter to retry the transfer if checksum or file size differs.

## [1.1.1] - 2024-01-18
### Added
- Added setup for FtpClient.ReadTimeout, FtpClient.DataConnectionConnectTimeout and FtpClient.DataConnectionReadTimeout which were all defaulting to 15 seconds.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Frends.FTP.UploadFiles.TaskConfiguration;
using Frends.FTP.UploadFiles.TaskResult;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Threading;

namespace Frends.FTP.UploadFiles.Tests;
Expand All @@ -22,7 +23,7 @@ public void DestinationAction_Append_NoRenameInTransfer()
Assert.IsTrue(result1.Success, result1.UserResultMessage);
Assert.IsTrue(result2.Success, result2.UserResultMessage);
Assert.AreEqual(1, result2.SuccessfulTransferCount);
Assert.AreEqual("mycontentmycontent", Helpers.GetFileFromFtp(nameof(DestinationAction_Append_NoRenameInTransfer), "file1.txt"));
Assert.AreEqual("mycontentmycontent", File.ReadAllText(Helpers.GetFileFromFtp(nameof(DestinationAction_Append_NoRenameInTransfer), "file1.txt")));
}

[TestMethod]
Expand All @@ -38,7 +39,7 @@ public void DestinationAction_Append_WithRenameInTransfer()
Assert.IsTrue(result1.Success, result1.UserResultMessage);
Assert.IsTrue(result2.Success, result2.UserResultMessage);
Assert.AreEqual(1, result2.SuccessfulTransferCount);
Assert.AreEqual("mycontentmycontent", Helpers.GetFileFromFtp(nameof(DestinationAction_Append_WithRenameInTransfer), "file1.txt"));
Assert.AreEqual("mycontentmycontent", File.ReadAllText(Helpers.GetFileFromFtp(nameof(DestinationAction_Append_WithRenameInTransfer), "file1.txt")));
}

private Result CallUploadFiles(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>

<TargetFramework>net471</TargetFramework>
<LangVersion>Latest</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>

Expand All @@ -11,6 +11,8 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
Expand All @@ -21,6 +23,10 @@
<ProjectReference Include="..\Frends.FTP.UploadFiles\Frends.FTP.UploadFiles.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="DotNetZip" Version="1.16.0" />
</ItemGroup>

<ItemGroup>
<Folder Include="DockerVolumes\data\" />
</ItemGroup>
Expand Down
88 changes: 84 additions & 4 deletions Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/Lib/Helpers.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
using FluentFTP;
using Frends.FTP.UploadFiles.TaskConfiguration;
using Frends.FTP.UploadFiles.Enums;
using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Frends.FTP.UploadFiles.Tests;

Expand All @@ -25,7 +29,9 @@ internal static Connection GetFtpsConnection()
Password = FtpPassword,
Port = FtpsPort,
SslMode = FtpsSslMode.Explicit,
CertificateHashStringSHA1 = Sha1Hash
CertificateHashStringSHA1 = Sha1Hash,
BufferSize = 4096,
VerifyOption = VerifyOptions.None
};

return connection;
Expand All @@ -39,7 +45,9 @@ internal static Connection GetFtpConnection()
UserName = FtpUsername,
Password = FtpPassword,
Port = FtpPort,
SslMode = FtpsSslMode.None
SslMode = FtpsSslMode.None,
BufferSize = 4096,
VerifyOption = VerifyOptions.None
};

return connection;
Expand All @@ -49,18 +57,90 @@ internal static string GetFileFromFtp(string subDir, string file)
{
try
{
var tmpFile = Path.GetTempFileName();
var tmpFile = Path.Combine(Path.GetDirectoryName(Path.GetTempFileName()), "test.zip");
using (var client = new FtpClient(FtpHost, FtpPort, FtpUsername, FtpPassword))
{
client.Connect();
client.SetWorkingDirectory(subDir);
client.DownloadFile(tmpFile, file);
}
return File.ReadAllText(tmpFile);
return tmpFile;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}

internal static string CreateLargeDummyZipFiles(string dir, int count)
{
var name = "LargeTestFile";
var extension = ".bin";

var subDir = Path.Combine(dir, "zips");
Directory.CreateDirectory(subDir);

for (int i = 0; i < count; i++)
{
var path = Path.Combine(subDir, name + i + extension);
var fs = new FileStream(path, FileMode.CreateNew);
fs.Seek(2048L * 1024 * 512, SeekOrigin.Begin);
fs.WriteByte(0);
fs.Close();
}

using var zipFile = new Ionic.Zip.ZipFile(new UTF8Encoding(false));
zipFile.UseZip64WhenSaving = Zip64Option.Never;

foreach (var file in Directory.GetFiles(subDir))
{
zipFile.AddFile(file, "");
}

zipFile.Save(Path.Combine(dir, "test.zip"));

return Path.Combine(dir, "test.zip");
}

internal static bool ExtractLargeZipFile(string source, string destination)
{
try
{
var output = new UnzipOutput();
using var zip = ZipFile.Read(source);
string path = null;
zip.ExtractProgress += (sender, e) => Zip_ExtractProgress(e, output, path);
zip.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently;
zip.ExtractAll(destination);
return true;
}
catch
{
return false;
}
}

private static void Zip_ExtractProgress(ExtractProgressEventArgs e, UnzipOutput output, string fullPath)
{
if (e.EventType == ZipProgressEventType.Extracting_AfterExtractEntry && !e.CurrentEntry.IsDirectory)
{
// Path.GetFullPath changes directory separator to "\".
if (e.ExtractLocation == null) output.ExtractedFiles.Add(Path.GetFullPath(fullPath));
else output.ExtractedFiles.Add(Path.GetFullPath(Path.Combine(e.ExtractLocation, e.CurrentEntry.FileName)));
}
}

public class UnzipOutput
{
/// <summary>
/// a List-object of extracted files.
/// </summary>
/// <example>"ExtractedFiles": ["C:\\temp\\sample.txt", "C:\\temp\\sample2.txt"]</example>
public List<string> ExtractedFiles { get; set; }

internal UnzipOutput()
{
ExtractedFiles = new List<string>();
}
}
}
Loading

0 comments on commit b950362

Please sign in to comment.