I am building a simple application that uploads a .txt file to a FTP server. I have done this before and i am using the same code as i used for the other application.
this is my code:
string localFilePath = #"\\fileprint\data\Groups\Operation\fileExports\dls\";
string archiveFilePath = #"\\fileprint\data\Groups\Operation\fileExports\dls\Archive\";
string logFilePath = #"C:\Users\lmy\Desktop\Logs";
string ftpServer = "ftp://server:21/home/out2233/tmp";
private string logFileName = "" + DateTime.Now.Year.ToString() + "-" + DateTime.Now.Month.ToString() + "-" + DateTime.Now.Day.ToString();
public void UploadFile()
{
try
{
string[] files = Directory.GetFiles(localFilePath);
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
string modified = file.Remove(60, 6);
string modifiedFile = Path.GetFileName(modified);
FtpWebRequest ftpReq = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpServer + modifiedFile));
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
ftpReq.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
ftpReq.UsePassive = true;
ftpReq.UseBinary = true;
ftpReq.KeepAlive = true;
ftpReq.Credentials = new NetworkCredential("out2233", "password");
ftpReq.EnableSsl = true;
FileInfo fileInfo = new FileInfo(localFilePath + #"\" + fileName);
FileStream fileStream = fileInfo.OpenRead();
byte[] fileContent = new byte[fileInfo.Length];
fileStream.Read(fileContent, 0, Convert.ToInt32(fileInfo.Length));
Stream writer = ftpReq.GetRequestStream();
writer.Write(fileContent, 0, fileContent.Length);
fileStream.Close();
writer.Close();
FtpWebResponse response = (FtpWebResponse)ftpReq.GetResponse();
AppendLogFile(response, "Uploaded Files: ", fileName);
MoveToArchive(file, archiveFilePath + fileName);
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
But it get this error:
exception = {"Cannot send a content-body with this verb-type."}
when the code reaches this line:
Stream writer = ftpReq.GetRequestStream();
I have googled this but i can only find ASP examples. I cant seem to find out what i am doing wrong here. Hope you guys can help me.
thanks!
Looks like, you're trying to list ftp directory content, with this line:
ftpReq.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
(http://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp.listdirectorydetails%28v=vs.110%29.aspx)
Try removing it, leaving only this line:
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
http://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp.uploadfile%28v=vs.110%29.aspx
Related
I create a windows form to download files from ftp from particular folder.
The user put the ftp details with username and password and folder name from which file will be download all the files. This will set by user one time and the all file from ftp describe folder will download everyday.
Example on FTP Folder Name is MyFolder where a.docx, b.docx etc it will download a.docx, b.docx everyday not other folder data need to download.
For download and list of file I use below function. Can you please tell me what I am doing mistake or how can I do this .
private void downloadFileFromFTP()
{
try
{
string[] files = GetFileList();
foreach (string file in files)
{
Download(file);
}
}
catch (Exception ex)
{
}
}
For Get The List of file
public string[] GetFileList()
{
string[] downloadFiles;
StringBuilder result = new StringBuilder();
WebResponse response = null;
StreamReader reader = null;
try
{
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri( "ftp://" + txtftpAddress.Text + "/")); //txtFtpAddress.Text + "/" + txtFTPFolderName + "/" + file
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential("UserNm", "passwd");
reqFTP.Method = WebRequestMethods.Ftp .ListDirectory;
reqFTP.Proxy = null;
reqFTP.KeepAlive = false;
reqFTP.UsePassive = false;
response = reqFTP.GetResponse();
reader = new StreamReader(response.GetResponseStream());
string line = reader.ReadLine();
while (line != null)
{
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
}
// to remove the trailing '\n'
result.Remove(result.ToString().LastIndexOf('\n'), 1);
return result.ToString().Split('\n');
}
catch (Exception ex)
{
if (reader != null)
{
reader.Close();
}
if (response != null)
{
response.Close();
}
downloadFiles = null;
return downloadFiles;
}
}
download the file form the folder
private void Download(string file)
{
try
{
string uri = "ftp://" + txtFtpAddress.Text.Trim() + "/" + "txtlodername.Text" + "/" + file;
Uri serverUri = new Uri(uri);
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
return;
}
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(txtFtpAddress.Text + "/" + txtFTPFolderName + "/" + file));
reqFTP.Credentials = new NetworkCredential("UserName", "mypass");
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.Proxy = null;
reqFTP.UsePassive = false;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream responseStream = response.GetResponseStream();
FileStream writeStream = new FileStream("D\\Temp" + file, 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);
}
writeStream.Close();
response.Close();
}
catch (WebException wEx)
{
MessageBox.Show(wEx.Message, "Download Error");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Download Error");
}
}
I think 3 lines of your Download method have to be corrected as follows:
1.
string uri = "ftp://" + txtFtpAddress.Text.Trim() + "/" + "txtlodername.Text" + "/" + file;
should be:
string uri = "ftp://" + txtFtpAddress.Text.Trim() + "/" + txtFTPFolderName.Text.Trim() + "/" + file;
2.
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(txtFtpAddress.Text + "/" + txtFTPFolderName + "/" + file));
should be:
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
3.
FileStream writeStream = new FileStream("D\\Temp" + file, FileMode.Create);
should be:
FileStream writeStream = new FileStream("D:\\Temp\\" + file, FileMode.Create);
I'm trying to download all files including sub folders from ftp in c#.
I created DownloadDiretory for recursion of the sub folders and DownloadFtpFile for downloading files.
The code works fine for the root folder file download, but it is not downloading any subfolder files.
Any suggestions?
Thanks in Advance.
public static void DownloadDiretory(string folderPath)
{
try
{
ConnectionsXml objXml = new ConnectionsXml();
AccountFtp account = objXml.GetAccountFtpDetails();
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + account.Website + "/" + folderPath);
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
request.Credentials = new NetworkCredential(account.UserId, account.Password);
request.Timeout = 360000;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
//FtpWebResponse response = GetFtpResponse(folderPath);
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream, true);
string filename;
while (!reader.EndOfStream)
{
filename = string.Empty;
filename = reader.ReadLine();
if (filename.Contains("<DIR>"))
{
filename = filename.Substring(filename.IndexOf("<DIR>", 0) + 5, filename.Length - (filename.IndexOf("<DIR>", 0) + 5));
filename = filename.Trim();
DownloadDiretory(folderPath + "/" + filename);
}
else
{
string[] files = filename.Split(' ');
filename = files[files.Length - 1];
DownloadFtpFile(folderPath, filename);
}
}
responseStream.Close();
response.Close();
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
public static void DownloadFtpFile(string folderName, string fileName)
{
try
{
ConnectionsXml objXml = new ConnectionsXml();
AccountFtp account = objXml.GetAccountFtpDetails();
string path = "ftp://" + account.Website + "/" + folderName + "/" + fileName;
FtpWebRequest request = (FtpWebRequest)WebRequest.CreateDefault(new Uri(path));
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(account.UserId, account.Password);
//request.Timeout = 360000;
request.KeepAlive = false;
request.UsePassive = true;
request.UseBinary = true;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
if(!Directory.Exists(#"F:\MPR\" + folderName))
{
Directory.CreateDirectory(#"F:\MPR\" + folderName);
}
FileStream fileStream = new FileStream(#"F:\MPR\" + folderName + #"\" + fileName, FileMode.Create);
byte[] bytesbuffer = new byte[32 * 1024];
int byteRead = responseStream.Read(bytesbuffer, 0, 2048);
while (byteRead > 0)
{
fileStream.Write(bytesbuffer, 0, byteRead);
byteRead = responseStream.Read(bytesbuffer, 0, 2048);
}
responseStream.Close();
fileStream.Close();
response.Close();
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
Your condition filename.Contains("DIR")) seems to be wrong. I have no private ftp server available, so I tried on ftp://test.talia.net. The folder "incoming" gets returned as
"drwxrwxr-x 2 ftp ftp 4096 Oct 15 07:32 incoming"
Files get returned as eg
"-rw-r--r-- 1 ftp ftp 10485760 Apr 19 2006 10mb.pak"
So try to check with filename.StartsWith("d").
Also, these lines:
filename = string.Empty;
filename = reader.ReadLine();
serve no real purpose. Better set filename to string.Empty before entering the loop.
I tried to download files, but all files with special character cannot be recognized. Other files can be downloaded, while file named asdf#code#.pdf cannot be downloaded.
Error:
The remote server returned an error: (550) File unavailable (e.g., file not found, no access).
In local, the file with correct name is created, but it is empty. The same thing happens on JPG files with # inside of the file names. how can I let them be recognized?
//Download the file from remote path on FTP to local path
private static void Download(string remotePath, string localPath)
{
FtpWebRequest reqFTP;
try
{
reqFTP = GetWebRequest(WebRequestMethods.Ftp.DownloadFile, remotePath);
FileStream outputStream = new FileStream(localPath, FileMode.Create);
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();
Console.WriteLine("File Download: ", remotePath + " is downloaded completely");
logWriter.WriteLog("File Download: ", remotePath + " is downloaded completely, status " + response.StatusDescription);
}
catch (Exception ex)
{
logWriter.WriteLog("File Download: ", "Cannot download file from " + remotePath + " to " + localPath + "\n" + " Erro Message: " + ex.Message);
}
}//End Download
//Web request for FTP
static public FtpWebRequest GetWebRequest(string method, string uri)
{
Uri serverUri = new Uri(uri);
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
return null;
}
try
{
var reqFTP = (FtpWebRequest)FtpWebRequest.Create(serverUri);
reqFTP.Method = method;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(userId, password);
reqFTP.Proxy = null;
reqFTP.KeepAlive = false;
reqFTP.UsePassive = false;
return reqFTP;
}
catch(Exception ex)
{
logWriter.WriteLog("Get Web Request: ","Cannot connect to " + uri + "\n" + "Error: " + ex.Message);
return null;
}
}
This might be by design: According to the URI standard, # is not a valid character in a URI. Thus, ftp://someServer/somePath/intro_to_c#.pdf is not a valid URI.
What you could do is to properly escape the file name when creating the URI:
string baseUri = "ftp://someServer/somePath/";
string file = "intro_to_c#.pdf";
string myUri = baseUri + HttpUtility.UrlEncode(file);
// yields ftp://someServer/somePath/intro_to_c%23.pdf
Alternatively, you could use the UriBuilder class, which handles escaping properly:
Uri myUri = new UriBuilder("ftp", "someServer", 21, "somePath/intro_to_c#.pdf");
// yields ftp://someServer:21/somePath/intro_to_c%23.pdf
I add some code and fixed it. Use hexEscape to escape "#" but it is not decent. Any one have idea to escape special characters in URI?
// Get the request using a specific URI
static public FtpWebRequest GetWebRequest(string method, string uri)
{
Uri serverUri = new Uri(uri);
**if (serverUri.ToString().Contains("#"))
{
serverUri = new Uri(serverUri.ToString().Replace("#", Uri.HexEscape('#')));
}**
Console.WriteLine(serverUri.ToString());
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
return null;
}
try
{
var reqFTP = (FtpWebRequest)FtpWebRequest.Create(serverUri);
reqFTP.Method = method;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(userId, password);
reqFTP.Proxy = null;
reqFTP.KeepAlive = false;
reqFTP.UsePassive = false;
return reqFTP;
}
catch (Exception ex)
{
logWriter.WriteLog("Get Web Request: ", "Cannot connect to " + uri + "\n" + "Error: " + ex.Message);
return null;
}
}
I'm creating a file uploader in asp.net and c#.
I just wanted to save that uploaded files to ftp server directly.
Is it possible? And if it is possible, how can I set that ftp server authentication information.
(127.0.0.1 is just an example. I couldn't write my real ip. And I have to get files using HTTP protocol. Some of our clients ISPs don't support ftp. That's the main problem.)
protected void submit_button_Click(object sender, EventArgs e)
{
string filename = Path.GetFileName(upload_file.FileName);
string fileExt = Path.GetExtension(upload_file.FileName);
if (fileExt == ".csv")
{
string folder = Server.MapPath("ftp://127.0.0.1/uploads/");
upload_file.SaveAs(folder + "/" + filename);
ltr.Text = "Successful.";
}
else
{
upload_file.BorderColor = System.Drawing.Color.Red;
ltr.Text = "File type must be .csv.";
}
}
Its pretty simple.
The below method just pass in the file name. Obviously change the directory in the StreamReader.
EDIT: Sorry just noticed you said your client doesnt support FTP so the below wont work.
public bool ftpTransfer(string fileName)
{
try
{
string ftpAddress = "127.0.0.1";
string username = "user";
string password = "pass";
using (StreamReader stream = new StreamReader("C:\\" + fileName))
{
byte[] buffer = Encoding.Default.GetBytes(stream.ReadToEnd());
WebRequest request = WebRequest.Create("ftp://" + ftpAddress + "/" + "myfolder" + "/" + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(username, password);
Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return false;
}
}
Edit: Reworked the filename.
string filepath = "~/txtfile/";//this is folder name wher you want to save the file
HttpFileCollection uploadedFiles = HttpContext.Current.Request.Files;
for (int i = 0; i < uploadedFiles.Count; i++)
{
HttpPostedFile userPostedFile = uploadedFiles[i];
if (userPostedFile.ContentLength == 0)
{
continue;
}
userPostedFile.SaveAs(Server.MapPath(filepath) + userPostedFile.filename);
} //save file on the server
Here is my code to download file from ftp server but it's case sensitive match.. could you please help me to download with out case match.
ex: if i'm trying to download "6Gt6hh.xml" but existing file in ftp sever is "6GT6hh.Xml". its not download with my code could you please help me.
private void Download(string file, ServerCredentials FtpCdrl, string DayOfYear, string dest, string ab)
{
try
{
string uri = "ftp://" + FtpCdrl.Host + "/" + FtpCdrl.DirPath.Replace("\\", "/") + "/" + DayOfYear + "/" + file;
Uri serverUri = new Uri(uri);
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
return;
}
if (!Directory.Exists(dest))
Directory.CreateDirectory(dest);
if (!Directory.Exists(dest + "\\" + ab))
Directory.CreateDirectory(dest + "\\" + ab);
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + FtpCdrl.Host + "/" + FtpCdrl.DirPath.Replace("\\", "/") + "/" + DayOfYear + "/" + file));
reqFTP.Credentials = new NetworkCredential(FtpCdrl.UID, FtpCdrl.Pwd);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.Proxy = null;
reqFTP.UsePassive = false;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream responseStream = response.GetResponseStream();
FileStream writeStream = new FileStream(dest + "\\" + ab + "\\" + file, 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);
}
status("File Downloaded Successfully: .\\" + ab + "\\" + file, Color.Green);
writeStream.Close();
response.Close();
failed = 0;
}
catch (WebException wEx)
{
failed++;
status("[Download Error]" + wEx.Message, Color.Red);
if (failed < 3)
Download(file, FtpCdrl, DayOfYear, dest, ab);
}
catch (Exception ex)
{
status("[Download Error]" + ex.Message, Color.Red);
}
}
public class ServerCredentials
{
public string Host, UID, Pwd, DirPath;
public int Pst;
public string Mail;
public string facility;
public string Batchextn;
public ServerCredentials(string _Host1, string _DirPath1, string _Uid1, string _Pwd1, string _Mail, int _Pst1, string _facility, string _batchextn)
{
Host = _Host1;
UID = _Uid1;
Pwd = _Pwd1;
DirPath = _DirPath1;
Pst = _Pst1;
Mail = _Mail;
facility = _facility;
Batchextn = _batchextn;
}
}
public List<ServerCredentials> Svr = new List<ServerCredentials>();
Uris are case sensetive and it is up to server to allow case insensetive acces to files. I.e. traditionally most HTTP servers ignore case in the path portion of Uri, but often respect case in Query portion.
In your case it looks like the FTP server you access enforces case match for file names (common for Unix/Linux servers) and may even have multiple files with different casing.
The correct implementation would be to list content first and than pick the file name from the list of files. The how to: List Directory Contents with FTP article covers this step.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://www.contoso.com/");
request.Credentials = new NetworkCredential ("anonymous","janeDoe#contoso.com");
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using(var response = (FtpWebResponse)request.GetResponse())
using(var responseStream = response.GetResponseStream())
using(var reader = new StreamReader(responseStream))
{
Console.WriteLine(reader.ReadToEnd());
}