I'm using FtpWebRequest to make directory Now, and I would get this exception like ftp error 550: File unavailable. Though I can make directory successfully sometimes, I always got this Exception.
And Below is my CheckDir function:
protected string CheckDir(string fullpath, string ip, string acc, string pwd)
{
string[] path = fullpath.Split(slash[1]);
bool result = false;
FtpWebRequest request = (FtpWebRequest)(WebRequest.Create(ip + path[2]));
request.Credentials = new NetworkCredential(acc, pwd);
request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
request.Timeout = 10000;
try
{
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
result = true;
}
}
catch (WebException ex)
{
FtpWebResponse response = (FtpWebResponse)ex.Response;
if (response != null && response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
{
request = (FtpWebRequest)WebRequest.Create(ip + path[2]);
request.Credentials = new NetworkCredential(acc, pwd);
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
request.GetResponse();
result = true;
}
else
{
result = false;
}
}
if (result == true)
return path[2];
else
return null;
}
I found that I got the way to check existed Directory. Then, I use Contains with ListDirecotyDetails.
Here is my function:
protected string CheckDir(string fullpath, string c_ip, string c_acc, string c_pwd)
{
string[] path = fullpath.Split(slash[1]);
bool result = false;
try
{
if (WebRequestMethods.Ftp.ListDirectoryDetails.Contains(c_ip + path[2]))
{
result = true;
}
else
{
FtpWebRequest request = (FtpWebRequest)(WebRequest.Create(c_ip + path[2]));
request.Credentials = new NetworkCredential(c_acc, c_pwd);
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.KeepAlive = false;
try
{
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
}
catch (Exception)
{
request.Abort();
result = false;
}
request.Abort();
result = true;
}
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
if (result == true)
return path[2];
else
return null;
}
Related
I wonder if this FtpWebRequest goes wrong and, it goes to the catch event. I have seen an example code where they posted what I have uncommented in the catch event, - to clean up the resources.
But I don't know what is the proper way to do that in this scenario? Should I just put all of those to: = null; or is this wrong to do? What is the proper way to do it?
cleanUp(sourceStream, ref response, ref requestStream, ref request);
void uploadimage()
{
String sourceimage = "C:/ESD/image_2.jpg";
Task<bool> task = FtpUploadFile(sourceimage);
if (task.IsFaulted == false)
{
MessageBox.Show(task.Result.ToString());
}
}
private Task closeRequestStreamAsync(Stream requestStream) { return Task.Run(() => { requestStream.Close(); }); }
public async Task<bool> FtpUploadFile(string filename)
{
//if exception occurs we want to be able to close these
FtpWebResponse response = null;
FtpWebRequest request = null;
FileStream sourceStream = null;
Stream requestStream = null;
try
{
bool isimage = false; String ext = Path.GetExtension(filename);
if (ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".bmp") { isimage = true; }
request = (FtpWebRequest)WebRequest.Create("ftp://someurl.com/Folder1/test1.jpg");
request.UsePassive = true;
if (isimage == true) { request.UseBinary = true; } //for images
if (isimage == false) { request.UseBinary = false; } //for text
request.KeepAlive = true; //keep the connection open
request.Method = WebRequestMethods.Ftp.UploadFile;
request.ConnectionGroupName = "Group1";
request.ServicePoint.ConnectionLimit = 4;
//These are the credentials.
request.Credentials = new NetworkCredential("username", "password");
sourceStream = File.OpenRead(filename);
byte[] buffer = new byte[sourceStream.Length];
await sourceStream.ReadAsync(buffer, 0, buffer.Length);
sourceStream.Close();
requestStream = await request.GetRequestStreamAsync();
await requestStream.WriteAsync(buffer, 0, buffer.Length);
//MPM This is the call that takes the time
await closeRequestStreamAsync(requestStream);
//response = (FtpWebResponse)request.GetResponse();
WebResponse responseWeb = await request.GetResponseAsync();
response = (FtpWebResponse)responseWeb;
if (response.StatusDescription.Contains("226"))
{
//This means that we successfully have uploaded the file!
}
response.Close();
return true;
}
catch (Exception ex)
{
string errMSG = string.Format("Upload File failed, exception: {0}", ex.Message);
//cleanUp(sourceStream, ref response, ref requestStream, ref request);
return false;
}
}
To ensure the web request, response and stream objects are closed even if an exception occurs, they should be defined in a using block.
The code can be simplified to :
var ext = Path.GetExtension(filename);
var imageExtensions=new[]{".jpg",".jpeg",".png",".gif",".bmp"};
var isimage = imageExtensions.Contains(ext);
var request = (FtpWebRequest)WebRequest.Create("ftp://someurl.com/Folder1/test1.jpg");
request.UseBinary =isimage;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.ConnectionGroupName = "Group1";
request.ServicePoint.ConnectionLimit = 4;
//These are the credentials.
request.Credentials = new NetworkCredential("username", "password");
using(var sourceStream = File.OpenRead(filename))
using(var requestStream = await request.GetRequestStreamAsync())
{
await sourceStream.CopyToAsync(requestStream);
}
using(var responseWeb = await request.GetResponseAsync())
{
var response = (FtpWebResponse)responseWeb;
if (response.StatusDescription.Contains("226"))
{
return true;
}
}
.....
I removed the KeepAlive and UsePassive setters because true is their default value.
A WebRequest by itself doesn't hold any resources so it doesn't implement IDisposable. The connection to the server is made when GetRequestStream() is called. The values that need disposing/closing are sourceStream, requestStream and responseWeb.
I have 1 issues when i try too send file using FTP from Azure WebJobs.
This throw alternatly 'The remote server returned an error: (530) Not logged in.', my code work great in localhost (on dev computer).
I have read all off thoses Post but i didn't find a way :
FTPWebRequest 530 Error: Not Logged in issue
FTP The remote server returned an error: (530) Not logged in
Fetching files from FTP server via Azure webjobs
Ftp to external server in azure webjob not working
Other but i have only 1 webjobs in my app service and the CPU was at 30% when the jobs running ..
File download from FTP fails only in Azure web app
Edit :
Code Make Directory
FtpWebRequest reqFTP = null;
Stream ftpStream = null;
string[] subDirs = directory.Split('/');
string currentDir = publishUrl;
foreach (string subDir in subDirs)
{
try
{
currentDir = currentDir + "/" + subDir;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(currentDir);
reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
reqFTP.UseBinary = true;
//reqFTP.UsePassive = true;
//reqFTP.KeepAlive = true;
reqFTP.Credentials = new NetworkCredential(userName, userPWD);
FtpWebResponse response = (FtpWebResponse)await reqFTP.GetResponseAsync();
ftpStream = response.GetResponseStream();
ftpStream.Close();
response.Close();
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
//directory already exist I know that is weak but there is no way to check if a folder exist on ftp...
}
}
Code Send File :
try
{
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential(userName, userPWD);
client.UploadFile(publishUrl, "STOR", localFileName);
return true;
}
}
catch (Exception exception)
{
//Console.Error.Write(exception.Message);
Console.WriteLine(exception.Message);
return false;
}
And log when i run code in Azure WebApp WebJobs (Failed) :
https://pastebin.com/vgTxqT5p
And log when i run code in local machine (Work Great) :
https://pastebin.com/hBpum8T0
I think the workaround was on WebJobs app style and normal function wasn't waiting. I'm going to change my code to use Async Await method for all my WebJobs program.
Any have a way ?
Thx in advance.
Bad way (and i didn't Like this) but it's work..... :
Change the Make Directory Function like this :
public static void MakeFTPDir(string publishUrl, string userName, string userPWD, string directory)
{
FtpWebRequest reqFTP = null;
Stream ftpStream = null;
string[] subDirs = directory.Split('/');
string currentDir = publishUrl;
foreach (string subDir in subDirs)
{
bool isNotCreated = true;
int iTentative = 0;
currentDir = currentDir + "/" + subDir;
while (isNotCreated)
{
iTentative++;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(currentDir);
reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
reqFTP.UseBinary = true;
reqFTP.UsePassive = true;
reqFTP.KeepAlive = true;
reqFTP.Credentials = new NetworkCredential(userName, userPWD);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
ftpStream = response.GetResponseStream();
ftpStream.Close();
response.Close();
}
catch(WebException webException)
{
FtpWebResponse excWebResponse = (FtpWebResponse)webException.Response;
if(excWebResponse.StatusCode == FtpStatusCode.NotLoggedIn)
{
Console.WriteLine("WebException ==> NotLoggedIn >> Tentative :" + iTentative);
isNotCreated = true;
}
else
{
Console.WriteLine(webException.Message);
isNotCreated = false;
}
}
catch (Exception exception)
{
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
if (response.StatusCode == FtpStatusCode.NotLoggedIn)
{
Console.WriteLine("Exception ==> NotLoggedIn >> Tentative :" + iTentative);
isNotCreated = true;
}
else
{
Console.WriteLine(exception.Message);
isNotCreated = false;
}
}
}
}
}
Change the send file function like this
public static bool SendFtpFile(string publishUrl, string userName, string userPWD, string localFileName)
{
bool isNotCreated = true;
int iTentative = 0;
while (isNotCreated)
{
iTentative++;
try
{
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential(userName, userPWD);
client.UploadFile(publishUrl, "STOR", localFileName);
return true;
}
}
catch (WebException webException)
{
FtpWebResponse excWebResponse = (FtpWebResponse)webException.Response;
if (excWebResponse.StatusCode == FtpStatusCode.NotLoggedIn)
{
Console.WriteLine("WebException ==> NotLoggedIn >> Tentative :" + iTentative);
isNotCreated = true;
}
else
{
Console.WriteLine(webException.Message);
return false;
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
return false;
}
}
return true;
}
Change the IfFileExistOnServer :
public static bool CheckIfFileExistsOnServer(string publishUrl, string userName, string userPWD, string fileName)
{
bool isNoCheck = true;
int iTentative = 0;
string azureBotUrl = publishUrl + "/" + fileName;
while (isNoCheck)
{
iTentative++;
try
{
var request = (FtpWebRequest)WebRequest.Create(azureBotUrl);
request.Credentials = new NetworkCredential(userName, userPWD);
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = true;
request.Method = WebRequestMethods.Ftp.GetFileSize;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
return true;
}
catch (WebException webException)
{
FtpWebResponse excWebResponse = (FtpWebResponse)webException.Response;
if (excWebResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
return false;
if (excWebResponse.StatusCode == FtpStatusCode.NotLoggedIn)
{
Console.WriteLine("WebException ==> NotLoggedIn >> Tentative :" + iTentative);
isNoCheck = true;
}
else
{
return false;
}
}
}
return false;
}
And Change RenameFileOnServer :
public static bool RenameFileOnServer(string publishUrl, string userName, string userPWD, string sourceFileName, string newFileName)
{
bool isNoRenameFile = true;
int iTentative = 0;
FtpWebRequest ftpRequest = null;
FtpWebResponse ftpResponse = null;
string azureBotUrl = publishUrl + "/" + sourceFileName;
while (isNoRenameFile)
{
iTentative++;
try
{
ftpRequest = (FtpWebRequest)WebRequest.Create(azureBotUrl);
ftpRequest.Credentials = new NetworkCredential(userName, userPWD);
ftpRequest.UseBinary = true;
ftpRequest.UsePassive = true;
ftpRequest.KeepAlive = true;
ftpRequest.Method = WebRequestMethods.Ftp.Rename;
ftpRequest.RenameTo = newFileName.Split('\\')[newFileName.Split('\\').Length - 1];
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
ftpResponse.Close();
ftpRequest = null;
return true;
}
catch (WebException webException)
{
FtpWebResponse excWebResponse = (FtpWebResponse)webException.Response;
if (excWebResponse.StatusCode == FtpStatusCode.NotLoggedIn)
{
Console.WriteLine("WebException ==> NotLoggedIn >> Tentative :" + iTentative);
isNoRenameFile = true;
}
else
{
return false;
}
Console.WriteLine(webException.Message);
}
catch (Exception)
{
return false;
}
}
return false;
}
I'm waiting a call from Ms Azure Support ...
I am checking a website is active or not using below code. If website is inactive like screen shot. I want to log the detailed error information from the response. how can i do it..? please suggest..
private static bool CheckWebSiteActive()
{
bool isWebSiteActive = false;
try
{
StreamReader sr = null;
Stream resst = null;
HttpWebResponse response = null;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(ConfigurationManager.AppSettings["webSiteToCheck"]);
request.Timeout = 10000;
request.AllowAutoRedirect = false; // find out if this site is up and don't follow a redirector
request.Method = "HEAD";
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException we)
{
using (WebResponse Wresponse = we.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse)Wresponse;
Console.WriteLine("Error code: {0}", httpResponse.StatusCode);
using (Stream data = Wresponse.GetResponseStream())
{
string text = new StreamReader(data).ReadToEnd();
Console.WriteLine(text);
}
}
//response = (HttpWebResponse)we.Response;
//resst = response.GetResponseStream();
//sr = new StreamReader(resst);
log.Error(sr.ReadToEnd());
}
isWebSiteActive = ((int)response.StatusCode == 200 && response.StatusCode == HttpStatusCode.OK) ? true : false;
}catch(Exception Ex)
{
log.Error(Ex.Message.ToString());
}
return isWebSiteActive;
}
Thanks in adv.
i'm using the below method to upload files from local server to FTP server, here i'm creating a new connection and initiating a new session each and every file uploading and closing the same. how to achieve this in single initiated session in c#.
this is my code
public bool UploadTempFilesToFTP()
{
string[] fileList;
try
{
ConfiguredValues conObj = new ConfiguredValues();
conObj.PickTheValuesFromConfigFile();
fileList = Directory.GetFiles(conObj.tempPath);
foreach (string FileName in fileList)
{
FtpWebRequest upldrequest = (FtpWebRequest)FtpWebRequest.Create(conObj.tempOutboundURL + FileName);
upldrequest.UseBinary = true;
upldrequest.KeepAlive = false;
upldrequest.Timeout = -1;
upldrequest.UsePassive = true;
upldrequest.Credentials = new NetworkCredential(conObj.user, conObj.pass);
upldrequest.Method = WebRequestMethods.Ftp.UploadFile;
string destinationAddress = conObj.tempPath;
FileStream fs = File.OpenRead(destinationAddress + FileName);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream requestStr = upldrequest.GetRequestStream();
requestStr.Write(buffer, 0, buffer.Length);
requestStr.Close();
requestStr.Flush();
FtpWebResponse response = (FtpWebResponse)upldrequest.GetResponse();
response.Close();
File.Delete(destinationAddress + FileName);
}
Console.WriteLine("Uploaded Successfully to Temp folder");
return true;
}
catch (Exception ex)
{
Console.WriteLine("Upload failed. {0}", ex.Message);
return false;
}
}
it's weird that i answer an old question but i try almost everything to upload multiple files to ftp with no luck while the solution is very simple and effective, using LOOPING - foreach solved the issue for me i use the below function to Upload the files in one simple step..
public void Uploadbulkftpfiles(string[] list)
{
bool ife;// is folder exists
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftpsite.com/folder");
request.Credentials = new NetworkCredential("Username", "Password");
request.Method = WebRequestMethods.Ftp.ListDirectory;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
ife = true;
}
catch (Exception)
{
ife = false;
}
/////////////////////////////////////////////begin of upload process
if (ife)//the folder is already exists
{
foreach (var str in list)
{
try
{
FtpWebRequest requestUP2 = (FtpWebRequest)WebRequest.Create("ftp://ftpsite.com/folder" + str);
requestUP2.Credentials = new NetworkCredential("UserName", "Password");
requestUP2.Method = WebRequestMethods.Ftp.UploadFile;
requestUP2.KeepAlive = false;
requestUP2.UsePassive = true;
using (Stream fileStream = File.OpenRead("ftp://ftpsite.com/folder" + str))
using (Stream ftpStream = requestUP2.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
}
catch (Exception ex1)
{
MessageBox.Show(ex1.Message);
}
}
}
else if (!ife)
{
//CREATE THE FOLDER
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp:ftpsite/folder");
request.Credentials = new NetworkCredential("UserName", "Password");
request.Method = WebRequestMethods.Ftp.MakeDirectory;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
}
catch (Exception excr) { MessageBox.Show(excr.Message); }
//UPLOAD THE FILES
foreach (var str in list)
{
try
{
FtpWebRequest requestUP2 = (FtpWebRequest)WebRequest.Create("ftp://ftpsite.com/folder" + str);
requestUP2.Credentials = new NetworkCredential("UserName", "Password");
requestUP2.Method = WebRequestMethods.Ftp.UploadFile;
requestUP2.KeepAlive = false;
requestUP2.UsePassive = true;
using (Stream fileStream = File.OpenRead("ftp://ftpsite.com/folder" + str))
using (Stream ftpStream = requestUP2.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
}
catch (Exception ex1)
{
MessageBox.Show(ex1.Message);
}
}
}
}
The ftp protocol is intended to works on request basis.
You start a request with a method (in your case UploadFile).
The only thing you can do is to KeepAlive your request to avoid connection closing
upldrequest.KeepAlive = true;
on every request you create except the last one. This will make a login only the first FTPWebRequest.
Then when you create the last FTPWebRequest, set
upldrequest.KeepAlive = false;
and it will close the connection when done.
I'm having a problem in uploading files to an ftp server.
the function works fine, but if try to use it in multithread, and when two threads tries to write the same file at the same time, I got error 550 in the second thread.
basically the first thread creates the file, while the second one raises the error.
here it is my code
internal bool UploadFtp(IResult result, string directoryPath, string filename, Stream fileContents, bool considerError550=true)
{
Thread.Sleep(3000);
directoryPath = directoryPath.TrimStart('\\');
string completePath = MachineConnectionParam.Url;
fileContents.Seek(0, SeekOrigin.Begin);
if (directoryPath != string.Empty && directoryPath != "\\")
completePath = completePath + directoryPath;
FtpWebResponse response = null;
try
{
completePath = completePath.TrimEnd('/');
filename = filename.TrimStart('/');
completePath = completePath + "/" + filename;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(completePath);
if (request == null)
{
result.SetError(Translate.InvalidUrl, completePath);
return false;
}
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UseBinary = true;
request.UsePassive = false;
request.KeepAlive = false;
//request.Timeout = 5000;
request.Proxy = null;
request.Credentials = new NetworkCredential(MachineConnectionParam.Username, MachineConnectionParam.Password);
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
fileContents.CopyTo(requestStream);
requestStream.Close();
response = (FtpWebResponse)request.GetResponse();
}
catch (Exception e)
{
result.SetError(e.Message);
return false;
}
finally
{
if (response != null)
response.Close();
}
return true;
}
any idea to solve it?
thank you