First time poster, long-time reader. I have a really annoying problem thats been getting on my nerves. Ive got a program set up so I listen for new files on an FTP server, if theres a new file I download it. From there I work on some of the information in the file, etc. My problem comes when I run through my sequence the second time. That is, on the first file I download everything is totally fine, but as soon as a new file gets detected and my program tries downloading it, my program just hangs.
private static void DownloadFile(string s)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://blabla.com/"+s);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential("xxx" ,"zzz");
using (FtpWebResponse partResponse = (FtpWebResponse)request.GetResponse())
{
Stream partReader = partResponse.GetResponseStream();
byte[] buffer = new byte[1024];
FileInfo fi = new FileInfo(path);
FileStream memStream = fi.Create();
while (true)
{
int bytesRead = partReader.Read(buffer, 0, buffer.Length - 1);
if (bytesRead == 0)
break;
memStream.Write(buffer, 0, bytesRead);
}
partResponse.Close();
memStream.Close();
}
Console.WriteLine(DateTime.Now + " file downloaded");
MoveFileToInProgress(s);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
The line it hangs on is this one:
using (FtpWebResponse partResponse = (FtpWebResponse)request.GetResponse())
The reason my method here is static is because Im just running it in a different project to test it.. My question here is, how come it only ever dies on the second file? Ive been staring myself blind for hours now!
I ran into this problem as well... try finishing your request first and then closing it before trying to retrieve the response. That worked for me (actually tried it after reading comment by MartinNielsen). Here is what I did.
// connect to the ftp site
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(ftpUri);
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpRequest.Credentials = new NetworkCredential(ftpUser, ftpPassword);
// setting proxy to null so that it does not go through the proxy
ftpRequest.Proxy = null;
// get file information
StreamReader fileStream = new StreamReader(filePath);
byte[] fileBytes = Encoding.UTF8.GetBytes(fileStream.ReadToEnd());
ftpRequest.ContentLength = fileBytes.Length;
fileStream.Close();
// open connection to ftp site
Stream ftpRequestStream = ftpRequest.GetRequestStream();
// write the file to the stream
ftpRequestStream.Write(fileBytes, 0, fileBytes.Length);
// close the stream
ftpRequestStream.Close();
// get the response from the server
FtpWebResponse ftpUploadResponse = (FtpWebResponse)ftpRequest.GetResponse();
string result = ftpUploadResponse.StatusDescription;
// close response
ftpUploadResponse.Close();
// return response to calling code
return result;
Here are a couple of the resources that I used when writing this code (won't let me post more than 2, there were more)
How to: Upload Files with FTP
Uploading a file -- "The requested URI is invalid for this FTP command"
I'm not expert on C# but I use this code to download files from my ftp:
public void Download(string filename)
{
// I try to download five times before crash
for (int i = 1; i < 5; i++)
{
try
{
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(Global.Path + "/" + filename);
ftp.Credentials = new NetworkCredential(User, Pass);
ftp.KeepAlive = false;
ftp.Method = WebRequestMethods.Ftp.DownloadFile;
ftp.UseBinary = true;
ftp.Proxy = null;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
string LocalDirectory = Application.StartupPath.ToString() + "/downloads/" + filename;
using (FileStream fs = new FileStream(LocalDirectory, FileMode.Create, FileAccess.Write, FileShare.None))
using (Stream strm = ftp.GetResponse().GetResponseStream())
{
contentLen = strm.Read(buff, 0, buffLength);
while (contentLen != 0)
{
fs.Write(buff, 0, contentLen);
contentLen = strm.Read(buff, 0, buffLength);
}
}
Process.Start(LocalDirectory);
break;
}
catch (Exception exc)
{
if (i == 5)
{
MessageBox.Show("Can't download, try number: " + i + "/5 \n\n Error: " + exc.Message,
"Problem downloading the file");
}
}
}
}
Tell me if it works for you :)
Related
In my code I want to upload and download a specific JSON-File to a FTP-Server.
The serializing works great and also the upload. When i look up the file via - for example - FileZilla, the content of the file is correct. (on the server)
But when i download this file with my application (and with my code - NOT with FileZilla), I don't get any exceptions, but the file is nearly empty. This is the only content:
{}
And here is my code for downloading:
string ResponseDescription = "";
FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create("ftp://" + "ftp.strato.com" + "/" + verzeichnis + "/" + file.Name);
req.Method = WebRequestMethods.Ftp.DownloadFile;
req.Credentials = new NetworkCredential(this.benutzer, this.passwort);
req.UseBinary = true;
req.UsePassive = false;
req.Proxy = null;
try
{
FtpWebResponse response = (FtpWebResponse)req.GetResponse();
Stream stream = response.GetResponseStream();
byte[] buffer = new byte[2048];
FileStream fs = new FileStream(destinationFolder + #"/" + destinationFile.Name, FileMode.Create);
int ReadCount = stream.Read(buffer, 0, buffer.Length);
while (ReadCount > 0)
{
fs.Write(buffer, 0, ReadCount);
ReadCount = stream.Read(buffer, 0, buffer.Length);
}
ResponseDescription = response.StatusDescription;
fs.Close();
stream.Close();
return true;
}
catch (Exception e)
{
MessageBox.Show(e.Message); // TODO - better Errorhandling
return false;
}
I found the solution. It was my mistake. The problem wasnt the download - the code was correct (as you said).
After downloading the file the JSON-Deserialization runs and here was the cause. I had a little mistake in my deserialization-logic.
I'm uploading large files to ftp site using this code.
Code
using (FileStream fs = new FileStream(FileLoc, FileMode.Open, FileAccess.Read))
{
string ftpUrl = string.Format("{0}/{1}", uploadUrl, uploadFileName);
FtpWebRequest requestObj = FtpWebRequest.Create(ftpUrl) as FtpWebRequest;
requestObj.Method = WebRequestMethods.Ftp.UploadFile;
requestObj.Credentials = new NetworkCredential(Uid, Pass);
using (Stream requestStream = requestObj.GetRequestStream())
{
byte[] buffer = new byte[8092];
int read = 0;
while ((read = fs.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, read);
}
requestStream.Flush();
if (fs != null)
{
fs.Close();
fs.Dispose();
}
if (requestStream != null)
{
requestStream.Close();
requestStream.Dispose();
}
}
}
Some times this code up-lode files very fine but some time it up-lodes some part of file not complete file and doesn't give any error.
Can any one help me why some time it upload only some part of file not hole file.
Here's the code we use for uploading to FTP. It looks very similar to your own. Nevertheleess, I post it for your reference as we haven't had any such reported failures
private void UploadFile(string fileToUpload)
{
Output = new Uri(Path.Combine(Output.ToString(), Path.GetFileName(fileToUpload)));
FtpWebRequest request = WebRequest.Create(Output) as FtpWebRequest;
request.Method = WebRequestMethods.Ftp.UploadFile;
// in order to work with Microsoft Windows Server 2003 + IIS, we can't use passive mode.
request.UsePassive = false;
request.Credentials = new NetworkCredential(username, password);
// Copy the contents of the file to the request stream.
Stream dest = request.GetRequestStream();
FileStream src = File.OpenRead(fileToUpload);
int bufSize = (int)Math.Min(src.Length, 1024);
byte[] buffer = new byte[bufSize];
int bytesRead = 0;
int numBuffersUploaded = 0;
do
{
bytesRead = src.Read(buffer, 0, bufSize);
dest.Write(buffer, 0, bufSize);
numBuffersUploaded++;
}
while (bytesRead != 0);
dest.Close();
src.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
if (response.StatusCode != FtpStatusCode.ClosingData)
{
Console.Error.WriteLine("Request {0}: Error uploading file to FTP server: {1} ({2})", Id, response.StatusDescription, response.StatusCode);
}
else
{
Console.Out.WriteLine("Request {0}: Successfully transferred file to {1}", Id, Output.ToString());
}
}
I get "System.NotSupportedException: The given path's format is not supported. at System.Security.Util.StringExpressionSet" when trying to download an item from an ftp(which have access to). The upload seems to work fine and is done similarly I'll post both functions below:
private void Download(string filePath, string fileName)
{
FtpWebRequest reqFTP;
try
{
//filePath = <<The full path where the file is to be created. the>>,
//fileName = <<Name of the file to be createdNeed not name on FTP server. name name()>>
Label1.Text = filePath + "/" + fileName;
FileStream outputStream = new FileStream(filePath + "/" + fileName, FileMode.Create);
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new
Uri("ftp://" + ftpServerIP + "/" + fileName));
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
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);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
outputStream.Close();
response.Close();
}
catch (Exception ex)
{
Label1.Text = ex.ToString();
}
}
public void Upload(string filename)
{
FileInfo fileInf = new FileInfo(filename);
string uri = "ftp://" + ftpServerIP + "/" + fileInf.Name;
FtpWebRequest reqFTP;
// Create FtpWebRequest object from the Uri provided
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP +"/" + fileInf.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;
// Notify the server about the size of the uploaded file
reqFTP.ContentLength = fileInf.Length;
// The buffer size is set to 2kb
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
// Opens a file stream (System.IO.FileStream) to read the file to be uploaded
FileStream fs = fileInf.OpenRead();
try
{
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream();
// Read from the file stream 2kb at a time
contentLen = fs.Read(buff, 0, buffLength);
// Till Stream content ends
while (contentLen != 0)
{
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
// Close the file stream and the Request Stream
strm.Close();
fs.Close();
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message, "Upload Error");
}
}
and these are the function calls
protected void btnDownload_Click(object sender, EventArgs e)
{
string FullServer = "ftp://" + ftpServerIP;
Download(FullServer, LbxServer.SelectedValue);
}
protected void btnUpload_Click(object sender, EventArgs e)
{
Upload(LbxLocal.SelectedValue);
}
Thank you all for any help on this matter.
I think you'll find that ftp://myservername is an invalid scheme for a new FileStream. Note that your FileStream represents the local target, not the remote file.
If your intent is to download a remote file to your local system, filePath should refer to a folder on your local network (e.g., C:\temp or \\somecomputer\share, etc.)
The following code is good for uploading text files, but it fails to upload JPEG files (not completely - the file name is good but the image is corrupted):
private void up(string sourceFile, string targetFile)
{
try
{
string ftpServerIP = ConfigurationManager.AppSettings["ftpIP"];
string ftpUserID = ConfigurationManager.AppSettings["ftpUser"];
string ftpPassword = ConfigurationManager.AppSettings["ftpPass"];
//string ftpURI = "";
string filename = "ftp://" + ftpServerIP + "//" + targetFile;
FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename);
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
ftpReq.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
StreamReader stream = new StreamReader(sourceFile);
Byte[] b = System.Text.Encoding.UTF8.GetBytes(stream.ReadToEnd());
stream.Close();
ftpReq.ContentLength = b.Length;
Stream s = ftpReq.GetRequestStream();
s.Write(b, 0, b.Length);
s.Close();
System.Net.FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();
MessageBox.Show(ftpResp.StatusDescription);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
I have another solution that can upload a file:
private void Upload(string sourceFile, string targetFile)
{
string ftpUserID;
string ftpPassword;
string ftpServerIP;
ftpServerIP = ConfigurationManager.AppSettings["ftpIP"];
ftpUserID = ConfigurationManager.AppSettings["ftpUser"];
ftpPassword = ConfigurationManager.AppSettings["ftpPass"];
FileInfo fileInf = new FileInfo(sourceFile);
FtpWebRequest reqFTP;
// Create FtpWebRequest object from the Uri provided
reqFTP = (FtpWebRequest)(FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "//" + targetFile)));
// Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
// Bypass default lan settings
reqFTP.Proxy = null;
// 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;
// Notify the server about the size of the uploaded file
reqFTP.ContentLength = fileInf.Length;
// The buffer size is set to 2kb
int buffLength = 2048;
Byte[] buff;
buff = new byte[buffLength];
int contentLen;
// Opens a file stream (System.IO.FileStream) to read the file to be uploaded
FileStream fs = fileInf.OpenRead();
try
{
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream();
// Read from the file stream 2kb at a time
long filesize = fs.Length;
int i=0;
contentLen = fs.Read(buff, 0, buffLength);
// Till Stream content ends
while (contentLen != 0)
{
Application.DoEvents();
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
i = i + 1;
//Double percentComp = (i * buffLength) * 100 / filesize;
//ProgressBar1.Value = (int)percentComp;
}
// Close the file stream and the Request Stream
strm.Close();
fs.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Upload Error");
}
}
But here I have the opposite problem - the picture is good, but the file name is corrupted.
I know it is because of the encoding, but I don't know how to make the bytes array have the desired encoding...
Try this bit:
private static void up(string sourceFile, string targetFile)
{
try
{
string ftpServerIP = ConfigurationManager.AppSettings["ftpIP"];
string ftpUserID = ConfigurationManager.AppSettings["ftpUser"];
string ftpPassword = ConfigurationManager.AppSettings["ftpPass"];
////string ftpURI = "";
string filename = "ftp://" + ftpServerIP + "//" + targetFile;
FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename);
ftpReq.UseBinary = true;
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
ftpReq.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
byte[] b = File.ReadAllBytes(sourceFile);
ftpReq.ContentLength = b.Length;
using (Stream s = ftpReq.GetRequestStream())
{
s.Write(b, 0, b.Length);
}
FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();
if (ftpResp != null)
{
MessageBox.Show(ftpResp.StatusDescription);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
You should be using a Stream to read binary files, not a StreamReader. StreamReader is designed to read text files only.
In your first code example, enable binary transfer: FtpWebRequest.UseBinary = true. Otherwise it will convert what it thinks are textual line endings between the various platform conventions (but are actually part of the image).
Your second snippet does it the right way. It uses FileStream, not StreamReader. StreamReader is only suitable for text files.
System.Text.Encoding.UTF8.GetBytes(stream.ReadToEnd());
Don't do this unless your stream's contents are text. Change your function to accept a boolean parameter "binary", and use the latter, working method if that flag is set.
If you have this problem: The requested FTP command is not supported when using HTTP
you need set proxy in Null or Nothing.
ftpReq.Proxy = null;
You can see this blog.
http://mycodetrip.com/2008/10/29/fix-for-error-the-requested-ftp-command-is-not-supported-when-using-http-proxy_118/comment-page-1/#comment-2825
Thanks.
I'm saving an image from a web request and something really weird is happening. On roughly half of the 8,000 images I'm downloading I get IOEXCEPTION errors:
ERROR_ACCESS_DENIED (5)
INVALID_PARAMETER (87)
Before I save the file using file.open, I check to make sure the file does not exist. The exception is thrown at this line of code:
fileStream = File.Open(destination, FileMode.Create, FileAccess.Write, FileShare.None);
Below is the code:
public static bool DownloadFile(string url, string destination)
{
bool success = false;
System.Net.HttpWebRequest request = null;
System.Net.WebResponse response = null;
Stream responseStream = null;
FileStream fileStream = null;
try
{
request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
request.Method = "GET";
request.Timeout = 100000; // 100 seconds
request.Proxy = System.Net.GlobalProxySelection.GetEmptyWebProxy();
response = request.GetResponse();
responseStream = response.GetResponseStream();
fileStream = File.Open(destination, FileMode.Create, FileAccess.Write, FileShare.None);
//fileStream = File.Create(destination);
// read up to ten kilobytes at a time
int maxRead = 10240;
byte[] buffer = new byte[maxRead];
int bytesRead = 0;
int totalBytesRead = 0;
// loop until no data is returned
while ((bytesRead = responseStream.Read(buffer, 0, maxRead)) > 0)
{
totalBytesRead += bytesRead;
fileStream.Write(buffer, 0, bytesRead);
}
// we got to this point with no exception. Ok.
success = true;
}
catch (System.Net.WebException we)
{
// something went terribly wrong.
success = false;
//MessageBox.Show(exp.ToString());
writeErrFile(we.ToString(), url);
//Debug.WriteLine(exp);
}
catch (System.IO.IOException ie)
{
// something went terribly wrong.
success = false;
//MessageBox.Show(ie.InnerException.ToString());
writeErrFile(ie.ToString(), destination + " -- " + url);
//Debug.WriteLine(exp);
}
catch (Exception exp)
{
// something went terribly wrong.
success = false;
//MessageBox.Show(exp.ToString());
writeErrFile(exp.ToString(), destination + " -- " + url);
//Debug.WriteLine(exp);
}
finally
{
// cleanup all potentially open streams.
if (null != responseStream)
responseStream.Close();
if (null != response)
response.Close();
if (null != fileStream)
fileStream.Close();
}
// if part of the file was written and the transfer failed, delete the partial file
if (!success && File.Exists(destination))
File.Delete(destination);
return success;
}
I've been stuck on this for a couple of days. Any help would be appreciated in unimaginable orders of magnitude.
Use file.exists() to check if the file exists and file.create or file.openwrite to write the file.
From your code I can't see how you are checking the file exists.