In my project I am downloading few files from a ftp created over IIS7 and also over linux server and saving it to my Appdata/Roamingfolder. Problem is coming when either I modify the content of the csv file or simply deleting the old file and replacing it with new file with same name but modified content.
Every time i have to rename that file and downloading the renamed file works. This indicates its downloading some cached image of the file which i am unable to locate either on my local system as well as over ftp server.
public static bool FTPFileDownload(string strFolderName, string
pathToStore, bool blIsSingleFile = true, string strFileType = "")
{
try
{
if (!Directory.Exists(pathToStore))
{
// Try to create the directory.
DirectoryInfo di = Directory.CreateDirectory(pathToStore);
}
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ConfigurationManager.AppSettings["FTPUrl"].ToString() + strFolderName);
request.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["FTPUser"].ToString(), ConfigurationManager.AppSettings["FTPPassword"].ToString());
request.Method = WebRequestMethods.Ftp.ListDirectory;
request.Proxy = null;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
StreamReader streamReader = new StreamReader(response.GetResponseStream());
System.Collections.Generic.List<string> directories = new System.Collections.Generic.List<string>();
string line = streamReader.ReadLine();
while (!string.IsNullOrEmpty(line))
{
//If extension is available match with extension and add.
bool blAddFile = false;
if (!String.IsNullOrEmpty(strFileType))
{
string strExt = Path.GetExtension(ConfigurationManager.AppSettings["FTPUrl"].ToString() + line).Remove(0, 1);
if (strExt.ToLower() == strFileType.ToLower())
blAddFile = true;
}
else
blAddFile = true;
if (blAddFile)
{
directories.Add(line);
}
line = streamReader.ReadLine();
}
streamReader.Close();
using (WebClient ftpClient = new WebClient())
{
ftpClient.Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["FTPUser"].ToString(), ConfigurationManager.AppSettings["FTPPassword"].ToString());
for (int i = 0; i <= directories.Count - 1; i++)
{
if (directories[i].Contains("."))
{
string path = ConfigurationManager.AppSettings["FTPUrl"].ToString() + strFolderName
+ (blIsSingleFile ? "" : "/" + directories[i].ToString());
string trnsfrpth = pathToStore + directories[i].ToString();
ftpClient.DownloadFile(path, trnsfrpth);
}
}
return true;
}
}
catch (Exception ex)
{
FileLogger.logMessage(ex.Message);
if (FileLogger.IsDebuggingLogEnabled)
{
FileLogger.HandleError("FTPFileDownload", ex, "Common Helper Error 4:");
}
return false;
}
}
I don't know what is going wrong with it. Either my code is wrong or the settings or environment over ftp server.
Please suggest.
Related
Using the Google Drive API to upload files. Multiple same console app is running at the same time to upload different parts of files in the folder and their files don't overlap. This hits the quota limit. Then a while-try-catch is implemented to re-execute the query whenever it throws the exception because of the quota limit. The list and create directory method works well but not the upload (i.e. create) method. Some files are missing when i checked from the Google Drive site
Tried using FileStream instead of MemoryStream but it seems not related.
public static Google.Apis.Drive.v3.Data.File uploadFile(DriveService _service, string _uploadFile)
{
bool again = true;
string[] p = _uploadFile.Split('/');
if (System.IO.File.Exists("C:/"+_uploadFile))
{
Google.Apis.Drive.v3.Data.File body = new Google.Apis.Drive.v3.Data.File();
body.Name = System.IO.Path.GetFileName(p[p.Length-1]);
body.Description = "";
body.MimeType = GetMimeType("C:/"+_uploadFile);
body.Parents = new List<string>() { ID };
// File's content.
System.IO.FileStream stream = new System.IO.FileStream("C:/" + _uploadFile, FileMode.Open);
try
{
FilesResource.CreateMediaUpload request = _service.Files.Create(body, stream, GetMimeType("C:/" + _uploadFile));
while (again)
{
try
{
request.Upload();
again = false;
}
catch (Exception e)
{
Console.WriteLine("uploadFile: "+p[p.Length-1]);
}
}
return body;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
return null;
}
}
else
{
Console.WriteLine("File does not exist: " + _uploadFile);
return null;
}
}
I'm using DotNetZip library to make multi-file zip archive and download it on the fly (no need to wait for download to start). However I can't make it to download instantly. From browser dev console, in network tab I noticed that first zip file is "transferred" and after being fully transferred it starts downloading.
Here is code fragment:
using (var vZipArchive = new ZipFile())
{
if (vFilesTable.Rows.Count > 0)
{
string vPathFormat = null;
string vKeyName = null;
string vPrimKey = null;
string vFileName = null;
vZipArchive.CompressionLevel = CompressionLevel.BestSpeed;
vZipArchive.CompressionMethod = CompressionMethod.Deflate;
vZipArchive.Comment = "Document Archive";
foreach (DataRow vFile in vFilesTable.Rows)
{
if (vKeyFieldName != null && !string.IsNullOrEmpty(vKeyFieldName))
{
vPathFormat = "{0}/";
}
else
{
vPathFormat = "/";
}
if (vFile.Table.Columns.Contains("FileName") && vFile.Table.Columns.Contains("PrimKey"))
{
vPrimKey = vFile["PrimKey"].ToString();
vFileName = vFile["FileName"].ToString();
if (vKeyFieldName != null)
{
vKeyName = vFile[vKeyFieldName].ToString();
}
string vPath = null;
if (vKeyFieldName != null)
{
vPath = string.Format(vKeyFieldName + " " + vPathFormat + "{1}", vKeyName, vFileName);
}
else
{
vPath = string.Format(vPathFormat + vFileName);
}
using (var vFileStream = vUserContext.GetFileStream(vRecordSource.ViewName, new Guid(vPrimKey)))
{
vFileStream.Position = 0;
vZipArchive.AddEntry(vPath, vFileStream);
}
}
else
{
throw new Exception("Select 'FileName' and 'PrimKey' fields in underlying DataSource");
}
} //end loop
pContext.Response.Clear();
pContext.Response.BufferOutput = false;
pContext.Response.ContentType = "application/zip";
pContext.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}.zip\"", vZipName));
vZipArchive.Save(pContext.Response.OutputStream);
}
else
{
return;
}
}
I also tried using ZipOutputStream and SharpCompress.dll library.
So, what I am missing to make it work? Or its impossible?
I am not getting an error but my files are not getting uploaded. Am trying to upload to a targetDirectory on SFTP.
public string TryUploads(string targetDirectory)
{
string _localDirectory = LocalDirectory; //The directory in SFTP server where the files are present
if (oSftp == null)
{
oSftp = Instance;
}
lock (thisLock)
{
try
{
oSftp.Connect();
List<string> fileList = Directory.GetFiles(_localDirectory, "*.*").ToList<string>();
oSftp.ChangeDirectory(targetDirectory);
if (fileList != null && fileList.Count() > 1)
{
for (int i = 0; i < fileList.Count(); i++)
{
string ftpFileName = Path.GetFileName(fileList[i]);
if (!String.IsNullOrEmpty(targetDirectory))
ftpFileName = String.Format("{0}/{1}", targetDirectory, ftpFileName);
using (var stream = new FileStream(Path.GetFileName(fileList[i]), FileMode.Create))
{
oSftp.BufferSize = 4 * 1024;
oSftp.UploadFile(stream, ftpFileName);
// stream.Close();
}
}
}
oSftp.Disconnect();
}
catch (Exception e)
{
throw new ApplicationException(e.Message);
}
}
return Strings.StatusOk;
}
I solved the issue. I needed to put the location of where am getting the file from in the stream
using (var stream = new FileStream(LocalDirectory + "\\" + Path.GetFileName(fileList[i]), FileMode.Open))
Solved. Files uploaded ;)
This is my program, and it work correctly if i put username and password :
try
{
var url = #"https://mail.google.com/mail/feed/atom";
var User = username;
var Pasw = password;
var encoded = TextToBase64(User + ":" + Pasw);
var myweb = HttpWebRequest.Create(url) as HttpWebRequest;
myweb.Method = "POST";
myweb.ContentLength = 0;
myweb.Headers.Add("Authorization", "Basic " + encoded);
var response = myweb.GetResponse();
var stream = response.GetResponseStream();
textBox1.Text += ("Connection established with" + User + Pasw);
}
catch (Exception ex)
{
textBox1.Text += ("Error connection. Original error: " + ex.Message);
now i want read string of texfile, split them and read username and password like this format: username:password . There is my code at the moment:
Stream myStream = null;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "c:\\";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.RestoreDirectory = true;
string file_name = "";
file_name = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + file_name;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
if ((myStream = openFileDialog1.OpenFile()) != null)
{
using (StringReader reader = new StringReader(file_name))
{
// Loop over the lines in the string.
int count = 0;
string line;
while ((line = reader.ReadLine()) != null)
{
string[] data = line.Split(':');
string username = data[0].Trim();
string password = data[1].Trim();
count++;
/* Console.WriteLine("Line {0}: {1}", count, line); */
}
reader.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
You open the file selected by the user, but then try to read from a variable file_name that is not the name of a file but the name of a well kwown folder. Perhaps you want this
try
{
if (openFileDialog1.FileName != string.Empty)
{
using (StreamReader reader = new StreamReader(openFileDialog1.FileName))
{
....
}
}
}
In this same code you use a StringReader, but instead you need a StreamReader to read from a file. StringReader takes the value passed in its constructor and return in the ReadLine call. Then you split the line at the colon but of course this is not the content of your file.
There are other problems in your code. For example, what do you do with the username and password loaded from the line? They are declared as local variables and not used anywhere, so at the next loop they are overwritten and lost.
So, a UserData class could be a possible answer
public class UserData
{
public string UserName {get; set;}
public string Password {get; set;}
}
and declare at the form global level an
List<UserData> data = new List<UserData>
and in your loop
public void button1_Click(object sender, EventArgs e)
{
try
{
if (openFileDialog1.FileName != string.Empty)
{
using (StreamReader reader = new StreamReader(openFileDialog1.FileName))
{
int count = 0;
string line;
while ((line = reader.ReadLine()) != null)
{
UserData d = new UserData();
string[] parts = line.Split(':');
d.UserName = parts[0].Trim();
d.Password = parts[1].Trim();
data.Add(d);
}
// At the loop end you could use the List<UserData> like a normal array
foreach(UserData ud in data)
{
Console.WriteLine("User=" + dd.UserName + " with password=" + dd.Password);
}
}
}
}
}
public void button2_Click(object sender, EventArgs e)
{
try
{
if(data.Count() == 0)
{
MessageBox.Show("Load user info first");
return;
}
var url = #"https://mail.google.com/mail/feed/atom";
var encoded = TextToBase64(data[0].UserName + ":" + data[0].Password);
.....
A warning note. Of course this is just demo code. Remember that in a real scenario saving passwords in clear text is a big security concern. The impact of this is relative to the context of your application but should not be downplayed. A better course of action is to store an hashing of the password values and apply the same hashing function when you need to compare password
You are creating StringReader from file_name varialbe, which is (according to your code)
string file_name = "";
file_name = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + file_name;
and points to nothere.
Also you have stream created for file being selected with open file dialog but you haven't use this stream.
I'm creating a C# application that needs to FTP to a directory to retrieve a file list. The following code works just fine. However, the folder that I'm FTPing to contains around 92,000 files. This code will not work in the way that I want it to for a file list of that size.
I'm looking only for files that begin with the string "c-". After doing some research, I'm not even sure how to begin trying to solve this issue. Is there any way I can modify this existing code for it to retrieve only those files?
public string[] getFileList() {
string[] downloadFiles;
StringBuilder result = new StringBuilder();
FtpWebRequest reqFTP;
try {
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpHost));
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUser, ftpPass);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
WebResponse response = reqFTP.GetResponse();
StreamReader 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);
reader.Close();
response.Close();
return result.ToString().Split('\n');
}
catch (Exception ex) {
System.Windows.Forms.MessageBox.Show(ex.Message);
downloadFiles = null;
return downloadFiles;
}
}
I think the LIST doesn't support wildcard search and in fact it might be vary from different FTP platform and depend the COMMANDS support
you will need to download all the files name in the FTP directory using LIST , probably in the async way.
Here is an alternative implementation along the similar lines. I've tested this with as many as 1000 ftp files, it might work for you. Complete source code can be found here.
public List<ftpinfo> browse(string path) //eg: "ftp.xyz.org", "ftp.xyz.org/ftproot/etc"
{
FtpWebRequest request=(FtpWebRequest)FtpWebRequest.Create(path);
request.Method=WebRequestMethods.Ftp.ListDirectoryDetails;
List<ftpinfo> files=new List<ftpinfo>();
//request.Proxy = System.Net.WebProxy.GetDefaultProxy();
//request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
request.Credentials = new NetworkCredential(_username, _password);
Stream rs=(Stream)request.GetResponse().GetResponseStream();
OnStatusChange("CONNECTED: " + path, 0, 0);
StreamReader sr = new StreamReader(rs);
string strList = sr.ReadToEnd();
string[] lines=null;
if (strList.Contains("\r\n"))
{
lines=strList.Split(new string[] {"\r\n"},StringSplitOptions.None);
}
else if (strList.Contains("\n"))
{
lines=strList.Split(new string[] {"\n"},StringSplitOptions.None);
}
//now decode this string array
if (lines==null || lines.Length == 0)
return null;
foreach(string line in lines)
{
if (line.Length==0)
continue;
//parse line
Match m= GetMatchingRegex(line);
if (m==null) {
//failed
throw new ApplicationException("Unable to parse line: " + line);
}
ftpinfo item=new ftpinfo();
item.filename = m.Groups["name"].Value.Trim('\r');
item.path = path;
item.size = Convert.ToInt64(m.Groups["size"].Value);
item.permission = m.Groups["permission"].Value;
string _dir = m.Groups["dir"].Value;
if(_dir.Length>0 && _dir != "-")
{
item.fileType = directoryEntryTypes.directory;
}
else
{
item.fileType = directoryEntryTypes.file;
}
try
{
item.fileDateTime = DateTime.Parse(m.Groups["timestamp"].Value);
}
catch
{
item.fileDateTime = DateTime.MinValue; //null;
}
files.Add(item);
}
return files;
}