Ich entwickle eine Lösung, bei der ein WCF-Dienst als Gateway zwischen einem FTP-Server agiert, auf den er remote über das FTP-Protokoll (Linux-Server) zugreifen muss, und einer Windows-Clientanwendung. Der Dienst selbst wird auf einem Windows IIS-Server gehostet.
Ich habe mein Modell auf einem Artikel über das Streamen von Dateien über http mit WCF basiert, aber das Problem ist:
Ich muss auf die Datei warten, die zunächst auf dem Windows Server heruntergeladen werden soll, bevor ich sie an den Client streamen kann, und das könnte ein größeres Leistungsproblem sein. Ich möchte die Dateien direkt vom FTP-Server zum Client streamen, ohne sie zuerst herunterzuladen.
Hier ist der Code..
public class TransferService : ITransferService{
Starksoft.Net.Ftp.FtpClient ftp = new Starksoft.Net.Ftp.FtpClient();
public RemoteFileInfo DownloadFile(DownloadRequest request)
{
RemoteFileInfo result = new RemoteFileInfo();
try
{
string filePath = System.IO.Path.Combine(@"C:\UploadFiles\ServerDownloadFiles", request.FileName);
System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
ftp = new Starksoft.Net.Ftp.FtpClient("127.0.0.1"); //remote ftp address
ftp.Open("user", "pass");
// hier wird auf die Datei gewartet, die vom FTP-Server heruntergeladen werden soll
System.IO.FileStream stream = new System.IO.FileStream(filePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
ftp.GetFileAsync(request.FileName, stream, true);
stream.Close();
stream.Dispose();
// dies wird gelesen und an den Client gestreamt
System.IO.FileStream stream2 = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
result.FileName = request.FileName;
result.Length = stream2.Length;
result.FileByteStream = stream2;
}
catch (Exception ex)
{
}
return result;
}
Der Client sieht so aus:
// start service client
FileTransferClient.TransferServiceClient client = new FileTransferClient.TransferServiceClient();
LogText("Start");
// Zieldatei löschen, falls bereits vorhanden
string filePath = System.IO.Path.Combine("Download", textBox1.Text);
if (System.IO.File.Exists(filePath)) System.IO.File.Delete(filePath);
// Stream vom Server abrufen
System.IO.Stream inputStream;
string fileName = textBox1.Text;
long length = client.DownloadFile(ref fileName, out inputStream);
// Serverstream auf Festplatte schreiben
using (System.IO.FileStream writeStream = new System.IO.FileStream(filePath, System.IO.FileMode.CreateNew, System.IO.FileAccess.Write))
{
int chunkSize = 2048;
byte[] buffer = new byte[chunkSize];
do
{
// Bytes aus dem Eingabestream lesen
int bytesRead = inputStream.Read(buffer, 0, chunkSize);
if (bytesRead == 0) break;
// Bytes in den Ausgabestream schreiben
writeStream.Write(buffer, 0, bytesRead);
// Fortschritt von Zeit zu Zeit melden
progressBar1.Value = (int)(writeStream.Position * 100 / length);
} while (true);
// Fortschritt melden
LogText("Fertig!");
writeStream.Close();
}
// Serviceclient schließen
inputStream.Dispose();
client.Close();
Was denkst du?
Take 2:
Stream stream;
public Stream GetStream(string filename)
{
Starksoft.Net.Ftp.FtpClient ftp = new Starksoft.Net.Ftp.FtpClient();
//string filePath = System.IO.Path.Combine(@"C:\UploadFiles\ServerDownloadFiles", filename);
//System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
ftp = new Starksoft.Net.Ftp.FtpClient("127.0.0.1");
ftp.Open("testuser", "123456");
stream = new MemoryStream();
ftp.GetFileAsyncCompleted += new EventHandler(ftp_GetFileAsyncCompleted);
this.IsBusy = true;
ftp.GetFileAsync(filename, stream, true);
return stream;
}
Servicevertrag:
[ServiceContract]
public interface IStreamingService
{
[OperationContract]
Stream GetStream(string filename);
[OperationContract]
Boolean GetBusyState();
}
Servicekonfiguration (Binding):