I have an FTP domain that I must to upload file txt to its FTP server the FTP domain looks like ftpes://domain.com, I never see the ftpes before, but when I upload by FileZilla it works success upload, but if I using my this code
FtpWebRequest ftpClient = (FtpWebRequest)FtpWebRequest.Create(FTPdestination+ i + ".txt");
ftpClient.Credentials = new System.Net.NetworkCredential(user, pass);
ftpClient.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
ftpClient.UseBinary = true;
ftpClient.EnableSsl = true;
ftpClient.KeepAlive = true;
System.IO.FileInfo fi = new System.IO.FileInfo(server+dtm+"_"+i+".txt");
ftpClient.ContentLength = fi.Length;
byte[] buffer = new byte[4097];
int bytes = 0;
int total_bytes = (int)fi.Length;
System.IO.FileStream fs = fi.OpenRead();
System.IO.Stream rs = ftpClient.GetRequestStream();
while (total_bytes > 0)
{
bytes = fs.Read(buffer, 0, buffer.Length);
rs.Write(buffer, 0, bytes);
total_bytes = total_bytes - bytes;
}
fs.Close();
rs.Close();
FtpWebResponse uploadResponse = (FtpWebResponse)ftpClient.GetResponse();
uploadResponse.Close();
The error message is
URI prefix not recognized
Please help me to solve my case.
ftpes:// is not a standard protocol prefix. But it is recognized by some FTP clients to mean "Explicit FTP over TLS/SSL".
With FtpWebRequest you specify that by using standard ftp:// protocol prefix and setting EnableSsl = true (what you do already).
See also Does .NET FtpWebRequest Support both Implicit (FTPS) and explicit (FTPES)?
Related
I have tried to download an FTP file using C# and have had various problems. What I want to achieve is to be able to show download progress in a progressBar. It is important that I use Windows Form and .Net.
I have tried two codes;
My first code works perfectly, that is, I can download the FTP file without problems.
CODE 1
FtpWebRequest dirFtp = ((FtpWebRequest)FtpWebRequest.Create(ficFTP));
dirFtp.KeepAlive = true;
dirFtp.UsePassive = UsePassive;
dirFtp.UseBinary = UseBinary;
// Los datos del usuario (credenciales)
NetworkCredential cr = new NetworkCredential(user, pass);
dirFtp.Credentials = cr;
FtpWebResponse response = (FtpWebResponse)dirFtp.GetResponse();
long size = (long)response.ContentLength;
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
using (FileStream writer = new FileStream(dirLocal, FileMode.Create))
{
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[2048];
readCount = responseStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
writer.Write(buffer, 0, readCount);
readCount = responseStream.Read(buffer, 0, bufferSize);
}
}
lblDescarga.Text = "¡Downloaded!";
reader.Close();
response.Close();
Problem with this code
My problem with this code is that I can't get the size of the FTP file to be able to use the progressBar, In theory this section of code would tell me the size of my file but it always returns -1:
long size = (long)response.ContentLength;
As this did not work as I wanted, I made a post and people recommended this solution FtpWebRequest FTP download with ProgressBar:
CODE 2
try
{
const string url = "ftp://185.222.111.11:21/patch/archive.zip";
NetworkCredential credentials = new NetworkCredential("user", "pass");
// Query size of the file to be downloaded
WebRequest sizeRequest = WebRequest.Create(url);
sizeRequest.Credentials = credentials;
sizeRequest.Method = WebRequestMethods.Ftp.GetFileSize;
int size = (int)sizeRequest.GetResponse().ContentLength;
progressBar1.Invoke(
(MethodInvoker)(() => progressBar1.Maximum = size));
// Download the file
WebRequest request = WebRequest.Create(url);
request.Credentials = credentials;
request.Method = WebRequestMethods.Ftp.DownloadFile;
using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(#"C:\tmp\archive.zip"))
{
byte[] buffer = new byte[10240];
int read;
while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, read);
int position = (int)fileStream.Position;
progressBar1.Invoke(
(MethodInvoker)(() => progressBar1.Value = position));
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
Problem with this code
The problem with this code is when it gets to this point:
int size = (int) sizeRequest.GetResponse (). ContentLength;
Remote server error: (550) File not available (eg file not found or not accessed).
The truth is that it is impossible to tell that you do not have permission if code 1 works well. However I have the normal permissions in FTP, could someone give me an idea please?
I have to upload some files on a FTP who use TLS with my C# application ( .net 3.5 )
With Filezila, no problems.
Now, with my C# code, i have a timeout exception and i really don't know why because all is ok with Filezila.
Here is my code :
public static bool AcceptAllCertificatePolicy(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
public static string Upload_SSL(string filenameSrc)
{
ServicePointManager.ServerCertificateValidationCallback = AcceptAllCertificatePolicy;
FileInfo fileInfSrc = new FileInfo(filenameSrc);
FtpWebRequest reqFTP;
// Create FtpWebRequest object from the Uri provided
if (strDirectory.Trim() != "")
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + strHost.Trim() + "/" + strDirectory.Trim() + "/" + fileInfSrc.Name.Trim()));
}
else
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + strHost.Trim() + "/" + fileInfSrc.Name.Trim()));
}
reqFTP.EnableSsl = true;
// Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential(strUser.Trim(), strPass.Trim());
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 = fileInfSrc.Length;
// The buffer size is set to 8kb
int buffLength = 8192;
byte[] buff = new byte[buffLength];
int contentLen;
// Opens a file stream (System.IO.FileStream) to read the file to be uploaded
FileStream fs = fileInfSrc.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)
{
fs.Close();
return (ex.Message);
}
return "ok";
}
Now, the call :
myFtp.Class1.strHost = "ftp://XXXXXXXXXXXXX";
myFtp.Class1.strPass = "*****************";
myFtp.Class1.strUser = "*********";
myFtp.Class1.nPort = 21;
myFtp.Class1.Upload_SSL(#"D:\Test.txt");
As information, if i try to use my code in order to upload a file on a NON TLS/SLL server, all is ok. So the problem appear to be only for the TLS/SSL ftp.
Anyone have some ideas please ?
Thanks a lot,
I kept the FTP:// in the host, so the url was FTP://FTP:/xxxxx
So i have a file locally that needs to keep the same name. But when i upload the file to the FTP i want to rename it, or add some ekstra to the file name. here is how i upload the file.
string localPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string fileName = "//XmlDocument.xml";
FtpWebRequest requestFTPUploader = (FtpWebRequest)WebRequest.Create("ftp://000.000.000/Documents" + fileName);
requestFTPUploader.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
requestFTPUploader.Method = WebRequestMethods.Ftp.UploadFile;
FileInfo fileInfo = new FileInfo(localPath + fileName);
FileStream fileStream = fileInfo.OpenRead();
int bufferLength = 2048;
byte[] buffer = new byte[bufferLength];
Stream uploadStream = requestFTPUploader.GetRequestStream();
int contentLength = fileStream.Read(buffer, 0, bufferLength);
while (contentLength != 0)
{
uploadStream.Write(buffer, 0, contentLength);
contentLength = fileStream.Read(buffer, 0, bufferLength);
}
uploadStream.Close();
fileStream.Close();
requestFTPUploader = null;
There is no relation whatsoever between the name of the file you're trying to upload and the name on the server you're uploading it to.
You can upload foo.jpg as bar.exe and no one will bat an eye.
So change this:
FtpWebRequest requestFTPUploader = (FtpWebRequest)WebRequest.Create("..." + fileName);
To this:
FtpWebRequest requestFTPUploader = (FtpWebRequest)WebRequest.Create("..." + ftpFileName);
And you're good to go.
I'm trying to write a program which will download a few files from and FTP, zip them up then upload them again to the same FTP location.
I have got it to attempt to download a file. If it fails, it will try again.
If NO errors occur, all files download and upload file.
If any errors occur when downloading, it will download them on the re-attempt, but fail then to upload.
I think the problems are down to not correctly closing a connection, but I can't for the life of me figure it out.
Here's my code; I've added where it fails:
Upload:
FileInfo fileInf = new FileInfo("directory" + zip + ".zip");
string uri = "ftp://address" + fileInf.Name;
FtpWebRequest reqFTP2;
reqFTP2 = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://address" + fileInf.Name));
reqFTP2.Credentials = new NetworkCredential("username", "password");
reqFTP2.KeepAlive = true;
reqFTP2.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP2.UseBinary = true;
reqFTP2.ContentLength = fileInf.Length;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
FileStream fs = fileInf.OpenRead();
try
{
Stream strm = reqFTP2.GetRequestStream(); //FAILS HERE
contentLen = fs.Read(buff, 0, buffLength);
while (contentLen != 0)
{
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
strm.Close();
fs.Close();
}
catch (Exception ex)
{
}
Download:
int errorOccured = 0;
while (errorOccured < 1)
{
FileStream outputStream = new FileStream("directory\\" + file, FileMode.Create);
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://address/" + file));
reqFTP.Credentials = new NetworkCredential("username", "password");
try
{
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
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();
errorOccured++;
}
catch (Exception er)
{
outputStream.Close();
}
The error 504 – Command not implemented for that parameter.
implies that some option you are using in there is not implemented by the target FTP server. I think that your code is resulting in a bizarre request, suggestion would be to look at the FTP chatter that your process creates on the server side. For exmaple, does the server support PASV mode? FTP protocol in ACTV mode (the default behavior) is always a pain because it explicitly causes the client to open a "file receive port" on port 20 and listen. While most servers support PASV mode transfers, it can become a pain if you don't put them in the PASV mode explicitly. So look at the chatter, see if the server is in PASV mode, and if you still have trouble, look at the chatter to see if there are "Extra Spaces" passed on during FTP negotiation. FTP is quite dinky and there can be several pitfalls. :-)
For starters, wrap your streams in using blocks so that they are disposed appropriately.
See MSDN for more details.
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