I'm in the situation where I need live logs, but they cannot be added to a database table. I need them live, so I figure instead of downloading the entire log file every 25 seconds, I should download part of the bytes. I don't see any parameters in the FtpWebRequest where I can specify this.
So the question is: How do I download part of a file via FtpWebRequest? (eg. the first 1024 bytes)
if i understand you right then You can just Keep Downloading Till The Download hit the Size of bytes you want then you can stop your download and save the actual bytes
EDIT :
create the byte[] you want for example :
byte[] buffer = new byte[2048];
you can download via FtpwebRequest using :
request.Method = WebRequestMethods.Ftp.DownloadFile;
then keep writing the bytes in the buffer
private void DownloadFile(string userName, string password, string ftpSourceFilePath, string localDestinationFilePath)
{
int bytesRead = 0;
byte[] buffer = new byte[2048];
FtpWebRequest request = CreateFtpWebRequest(ftpSourceFilePath, userName, password, true);
request.Method = WebRequestMethods.Ftp.DownloadFile;
Stream reader = request.GetResponse().GetResponseStream();
FileStream fileStream = new FileStream(localDestinationFilePath, FileMode.Create);
while (true)
{
bytesRead = reader.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
break;
fileStream.Write(buffer, 0, bytesRead);
}
fileStream.Close();
}
Related
My question is about create a browser that recognize a streaming video and then save it on a local directory.
I can use c#, Someone can help me and give me some advise.
At the beginning I think that I can use c# and an array of byte to get stream but I have some problems of implementation because I cannot found the steam.
This is the code:
public void StreamDownload(string currentUrl,string fileath)
{
int dataLength;
int bytesRead;
var filePath = System.IO.Path.Combine(fileath, "test");
if (File.Exists(filePath))
File.Delete(filePath);
WebRequest req = WebRequest.Create(currentUrl);
WebResponse response = req.GetResponse();
string oFileName = System.IO.Path.GetFileName("test");
Stream dataStream = response.GetResponseStream();
byte[] buffer = new byte[1024];
FileStream oFile = new FileStream(oFileName, FileMode.Append);
dataLength = (int)response.ContentLength;
do
{
bytesRead = dataStream.Read(buffer, 0, buffer.Length);
oFile.Write(buffer, 0, bytesRead);
}
while (bytesRead != 0);
File.WriteAllBytes(filePath, buffer);
}
The problem is that it save HTML page and not the stream
wait some experts XD
thank you.
I'm using .NET 3.5 and I need to transfer by FTP some files.
I don't want to use files because I manage all by using MemoryStream and bytes arrays.
Reading these articles (article and article), I made my client.
public void Upload(byte[] fileBytes, string remoteFile)
{
try
{
string uri = string.Format("{0}:{1}/{2}", Hostname, Port, remoteFile);
FtpWebRequest ftp = (FtpWebRequest)WebRequest.Create(uri);
ftp.Credentials = new NetworkCredential(Username.Normalize(), Password.Normalize());
ftp.UseBinary = true;
ftp.UsePassive = true;
ftp.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream localFileStream = new MemoryStream(fileBytes))
{
using (Stream ftpStream = ftp.GetRequestStream())
{
int bufferSize = (int)Math.Min(localFileStream.Length, 2048);
byte[] buffer = new byte[bufferSize];
int bytesSent = -1;
while (bytesSent != 0)
{
bytesSent = localFileStream.Read(buffer, 0, bufferSize);
ftpStream.Write(buffer, 0, bufferSize);
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteLog(logs, "Errore Upload", ex);
throw;
}
}
The FTP client connects, writes and close correctly without any error. But the written files are corrupted, such as PDF cannot be opened and for DOC/DOCX Word shows a message about file corruption and tries to restore them.
If I write to a file the same bytes passed to the Upload method, I get a correct file. So the problem must be with FTP transfer.
byte[] fileBytes = memoryStream.ToArray();
File.WriteAllBytes(#"C:\test.pdf", fileBytes); // --> File OK!
ftpClient.Upload(fileBytes, remoteFile); // --> File CORRUPTED on FTP folder!
You need to use bytesSent in the Write call:
bytesSent = localFileStream.Read(buffer, 0, bufferSize);
ftpStream.Write(buffer, 0, bytesSent);
Otherwise you write too many bytes in the last round.
I have got a code to download a file using ftprequest
FtpWebRequest requestFileDownload = (FtpWebRequest)WebRequest.Create("ftp://localhost/Source/" + fileName);
requestFileDownload.Credentials = new NetworkCredential("khanrahim", "arkhan22");
requestFileDownload.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse responseFileDownload = (FtpWebResponse)requestFileDownload.GetResponse();
Stream responseStream = responseFileDownload.GetResponseStream();
FileStream writeStream = new FileStream(localPath + fileName, FileMode.Create);
int Length = 2048;
Byte[] buffer = new Byte[Length];
int bytesRead = responseStream.Read(buffer, 0, Length);
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = responseStream.Read(buffer, 0, Length);
}
responseStream.Close();
writeStream.Close();
Now my need is that i need to delete the file from ftpserver once download is complete using the same requset.
I did try appending
requestFileDownload.Method = WebRequestMethods.Ftp.deleteFile;
before closing the request ..But it is not working.
How can i delete the file using the same request.
Objects created by WebRequest.Create can be used for exactly one request. Since there is no "GET and DELETE" method in FTP you need to create another FtpWebRequest with the same configuration and send delete request with that new FtpWebRequest.
I need to upload some DATA inside and FTP server.
Following stackoverflow posts on how to upload a FILE inside and FTP everything works.
Now i am trying to improve my upload.
Instead collecting the DATA, writing them to a FILE and then upload the file inside the FTP i want to collect the DATA and upload them without creating a local file.
To achieve this i do the following:
string uri = "ftp://" + ftpServerIp + "/" + fileToUpload.Name;
System.Net.FtpWebRequest reqFTP;
// Create FtpWebRequest object from the Uri provided
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIp + "/" + fileToUpload.Name));
// Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
// By default KeepAlive is true, where the control connection is not closed after a command is executed.
reqFTP.KeepAlive = false;
// Specify the command to be executed.
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
// Specify the data transfer type.
reqFTP.UseBinary = true;
byte[] messageContent = Encoding.ASCII.GetBytes(message);
// Notify the server about the size of the uploaded file
reqFTP.ContentLength = messageContent.Length;
int buffLength = 2048;
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream();
// Write Content from the file stream to the FTP Upload Stream
int total_bytes = (int)messageContent.Length;
while (total_bytes > 0)
{
strm.Write(messageContent, 0, buffLength);
total_bytes = total_bytes - buffLength;
}
strm.Close();
Now what happen is the following:
i see the client connecting to the server
the file is created
no data are transferred
at some point the thread is terminated the connection is closed
if i inspect the uploaded file is empty.
the DATA i want to to transfer is a STRING TYPE, that is why i do byte[] messageContent = Encoding.ASCII.GetBytes(message);
what am i doing wrong?
moreover: if i encode date with ASCII.GetBytes, on the remote server will i have a TEXT file or a file with some Bytes?
thank you for any suggestion
One issue that I see with the code is that you are writing the same bytes to the server on each iteration:
while (total_bytes > 0)
{
strm.Write(messageContent, 0, buffLength);
total_bytes = total_bytes - buffLength;
}
You need to change the offset position by doing something like this:
while (total_bytes < messageContent.Length)
{
strm.Write(messageContent, total_bytes , bufferLength);
total_bytes += bufferLength;
}
You are trying to write more data than you have. You code writes blocks of 2048 bytes at a time, and if the data is less, you will tell the write method to try to access bytes that are outside the array, which it of course won't.
All you should need to write the data is:
Stream strm = reqFTP.GetRequestStream();
strm.Write(messageContent, 0, messageContent.Length);
strm.Close();
If you need to write the data in chunks, you need to keep track of the offset in the array:
int buffLength = 2048;
int offset = 0;
Stream strm = reqFTP.GetRequestStream();
int total_bytes = (int)messageContent.Length;
while (total_bytes > 0) {
int len = Math.Min(buffLength, total_bytes);
strm.Write(messageContent, offset, len);
total_bytes -= len;
offset += len;
}
strm.Close();
I'm using the following C# code to FTP a ~40MB CSV file from a remote service provider. Around 50% of the time, the download hangs and eventually times out. In my app log, I get a line like:
> Unable to read data from the transport
> connection: A connection attempt
> failed because the connected party did
> not properly respond after a period of
> time, or established connection failed
> because connected host has failed to
> respond.
When I download the file interactively using a graphical client like LeechFTP, the downloads almost never hang, and complete in about 45 seconds. I'm having a hell of a time understanding what's going wrong.
Can anyone suggest how I can instrument this code to get more insight into what's going on, or a better way to download this file? Should I increase the buffer size? By how much? Avoid the buffered writes to disk and try to swallow the whole file in memory? Any advice appreciated!
...
private void CreateDownloadFile()
{
_OutputFile = new FileStream(_SourceFile, FileMode.Create);
}
public string FTPDownloadFile()
{
this.CreateDownloadFile();
myReq = (FtpWebRequest)FtpWebRequest.Create(new Uri(this.DownloadURI));
myReq.Method = WebRequestMethods.Ftp.DownloadFile;
myReq.UseBinary = true;
myReq.Credentials = new NetworkCredential(_ID, _Password);
FtpWebResponse myResp = (FtpWebResponse)myReq.GetResponse();
Stream ftpStream = myResp.GetResponseStream();
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
int bytesRead = 0;
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
_OutputFile.Write( buffer, 0, readCount );
readCount = ftpStream.Read( buffer, 0, bufferSize );
Console.Write( '.' ); // show progress on the console
bytesRead += readCount;
}
Console.WriteLine();
logger.logActivity( " FTP received " + String.Format( "{0:0,0}", bytesRead ) + " bytes" );
ftpStream.Close();
_OutputFile.Close();
myResp.Close();
return this.GetFTPStatus();
}
public string GetFTPStatus()
{
return ((FtpWebResponse)myReq.GetResponse()).StatusDescription;
}
I tried to use FTPClient as suggested above and got the same timeout error, FTPClient uses FtpWebRequest so I must be missing something but I don't see the point.
After some more research I found that -1 is the value for infinity
For my purpose it is okay to use infinity so I went with that, problem solved.
Here is my code:
//gets file from FTP site.
FtpWebRequest reqFTP;
string fileName = #"c:\downloadDir\localFileName.txt";
FileInfo downloadFile = new FileInfo(fileName);
string uri = "ftp://ftp.myftpsite.com/ftpDir/remoteFileName.txt";
FileStream outputStream = new FileStream(fileName, FileMode.Append);
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.KeepAlive = false;
reqFTP.Timeout = -1;
reqFTP.UsePassive = true;
reqFTP.Credentials = new NetworkCredential("userName", "passWord");
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = ftpStream.Read(buffer, 0, bufferSize);
Console.WriteLine("Connected: Downloading File");
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
Console.WriteLine(readCount.ToString());
}
ftpStream.Close();
outputStream.Close();
response.Close();
Console.WriteLine("Downloading Complete");
I suggest you don't use FtpWebRequest for FTP access. FtpWebRequest is the most brain-dead FTP API I have every seen.
Currently I use FtpClient http://www.codeplex.com/ftpclient
I also have had good luck with IndySockets http://www.indyproject.org/index.en.aspx
I haven't dealt with FTP on a code level, but FTP supports resuming. Maybe you could have it automatically try to resume the upload when it times out