Files
DearFTP/DearFTP/Connection/Commands/RetrieveCommand.cs
2019-07-20 17:51:08 +02:00

92 lines
2.7 KiB
C#

using System;
using System.IO;
namespace DearFTP.Connection.Commands
{
class RetrieveCommand : ICommand
{
public const int BufferSize = 4096;
public string[] Aliases { get; } = new string[]
{
"RETR"
};
public void Execute(Session session, FtpStream stream, string alias, string argument)
{
var dataConnection = session.DataConnection;
if (!dataConnection.IsTlsProtected && !dataConnection.IsAvailable)
{
stream.Send(ResponseCode.DataConnectionOpenError, "Passive mode not activated.");
return;
}
var (_, realPath, isDirectory) = session.NavigablePath.GetSystemFilePath(argument);
if (realPath == null)
{
stream.Send(ResponseCode.FileUnavailable, "Requested file does not exist.");
return;
}
if (isDirectory)
{
stream.Send(ResponseCode.FileUnavailable, "Requested file is a directory.");
return;
}
stream.Send(ResponseCode.FileStatusOK, "File coming.");
if (dataConnection.IsTlsProtected && !dataConnection.IsAvailable)
{
stream.Send(ResponseCode.DataConnectionOpenError, "Passive mode not activated.");
return;
}
int restartPosition = session.RestartPosition;
session.RestartPosition = 0;
SendFile(dataConnection.Stream, realPath, restartPosition);
dataConnection.Close();
stream.Send(ResponseCode.CloseDataConnection, "File sent.");
}
private void SendFile(Stream stream, string path, int offset)
{
using (var file = File.OpenRead(path))
{
if (offset != 0)
{
file.Seek(offset, SeekOrigin.Begin);
}
Span<byte> buffer = stackalloc byte[BufferSize];
long bytesToWrite = Math.Min(file.Length - file.Position, BufferSize);
while (file.Read(buffer) > 0)
{
try
{
if (bytesToWrite < BufferSize)
{
stream.Write(buffer.Slice(0, (int)bytesToWrite));
break;
}
stream.Write(buffer);
}
catch (Exception)
{
return;
}
bytesToWrite = Math.Min(file.Length - file.Position, BufferSize);
}
}
}
}
}