The files that I need to overwrite are on my local machine. The files that I am retrieving are from my FTP Server. The files are all of the same names, but differ in bytes, e.g., they are updated.
I am using files on my local machine as target files - meaning that I use their names to easily find them on the FTP server.
This is the code that I have written:
private void getFiles () {
string startupPath = Application.StartupPath;
/*
* This finds the files within the users installation folder
*/
string[] files = Directory.GetFiles(startupPath + "\\App_Data", "*.*",
SearchOption.AllDirectories);
foreach (string s in files)
{
/*
* This gets the file name
*/
string fileName = Path.GetFileName(s);
/*
* This gets the folder and subfolders after the main directory
*/
string filePath = s.Substring(s.IndexOf("App_Data"));
downloadFile("user:pass#mysite.tk/updates/App_Data/" + fileName,
startupPath + "\\" + filePath);
}
}
private void downloadFile (string urlAddress, string location)
{
using (WebClient webClient = new WebClient())
{
System.Uri URL = new System.Uri("ftp://" + urlAddress);
webClient.DownloadFileAsync(URL, location);
}
}
After the code finishes, for some reason, the files in the sub-folders are showing as 0KB. This is strange because I know that the every file on my FTP Server is greater than 0KB.
My question is: Why are the files in the subfolders showing as 0KB?
If this post is in anway unclear please let me know and I will do my best to clarify.
In answer to the quesiton in the comments, the following would be one possible way to do this, however it is unclear if getFiles is supposed to be a blocking method or not. In my example I assume it is (the method will not exit until all downloads have completed). I'm not sure about the functionality since I am writing this off the top of my head, but its a general idea.
private void getFiles () {
string startupPath = Application.StartupPath;
/*
* This finds the files within the users installation folder
*/
string[] files = Directory.GetFiles(startupPath + "\\App_Data", "*.*",
SearchOption.AllDirectories);
using (WebClient client = new WebClient())
{
int downloadCount = 0;
client.DownloadDataCompleted +=
new DownloadDataCompletedEventHandler((o, e) =>
{
downloadCount--;
});
foreach (string s in files)
{
/*
* This gets the file name
*/
string fileName = Path.GetFileName(s);
/*
* This gets the folder and subfolders after the main directory
*/
string filePath = s.Substring(s.IndexOf("App_Data"));
downloadFile(client, "user:pass#mysite.tk/updates/App_Data/" + fileName,
startupPath + "\\" + filePath);
downloadCount++;
}
while (downloadCount > 0) { }
}
}
private void downloadFile (WebClient client, string urlAddress, string location)
{
System.Uri URL = new System.Uri("ftp://" + urlAddress);
client.DownloadFileAsync(URL, location);
}
You could use FTPWebRequest for this.
http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx
Related
enter image description here
I am creating a dynamic folder as seen in the design in the image. I need to download two file types of data in a link to this folder I created, but how can I download it to the folder I created?
klasor = textBox1.Text;
var yol = Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + #"Beyza\source\" + klasor);
In this way, I create a folder in the 'klasor' variable.
public void indirButon_Click(object sender, EventArgs e)
{
string fileName = "C:\\Users\\Hilal Beyza\\Desktop\\projeler\\LinkProgram\\LinkProgram\\bin\\Debug\\Hilal Beyza\\yol\\webcams.mp4";
WebClient web = new WebClient();
web.DownloadFileCompleted += new AsyncCompletedEventHandler(Dosyaİndirme);
Uri DosyaAdresi = new Uri(label3.Text);
web.DownloadFile(DosyaAdresi, fileName);
}
I am giving my downloaded file a static path as above. How can I transfer this to the file I created?
Recommendations: When you write a program try to name components with a logic name, example txtUri, txtFolderName, btnDownload, this facilitates understanding.
If you have a File Name and Dynamic Folder it's possible.
public void indirButon_Click(object sender, EventArgs e)
{
string fileName = GetFileName("webcams.mp4");
WebClient web = new WebClient();
web.DownloadFileCompleted += new AsyncCompletedEventHandler(DosyaIndirme);
Uri DosyaAdresi = new Uri(label3.Text);
web.DownloadFile(DosyaAdresi, fileName);
}
This method Get File Name with new Dynamicly Folder.
private static string GetFileName(string fileName)
{
string klasor = textBox1.Text;
string directoryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"Hilal Beyza\source\", klasor);
if (!Directory.Exists(directoryPath))
Directory.CreateDirectory(directoryPath);
return Path.Combine(directoryPath, fileName);
}
If User pass complete path you need remove adapt the directoryPath
string directoryPath = Path.Combine(textBox1.Text);
The image uploading is working perfectly in the development server in the windows environment but when I run the code in the Remote Linux server, the files get uploaded but in the root folder and for which the files can not be accessed by the website.
public async Task<IActionResult> Index(IList<IFormFile> files,Type type)
{
Startup.Progress = 0;
foreach (IFormFile source in files)
{
if (isFileImage(source))
{
string filename = ContentDispositionHeaderValue.Parse(source.ContentDisposition).FileName.ToString().Trim('"');
filename = this.EnsureCorrectFilename(filename);
string serverFilePath = this.GetPathAndFilename(filename);
try
{
await source.CopyToAsync(new FileStream(serverFilePath,FileMode.Create));
}
catch (Exception e)
{
}
finally
{
}
}
}
return Content("Success");
}
private string GetPathAndFilename(string filename)
{
string path = Path.Combine(Directory.GetCurrentDirectory(),#"wwwroot\images\materials", filename);
return path;
}
This is the code responsible for uploading an image. In the development windows environment, it works perfectly as the files get saved in the "wwwroot\images\materials" folder.
But when the code is run the Remote Linux serves the files get uploaded but are saved in the root folder with "wwwroot\images\materials*.jpg" name. Even when running the code in development mode in the Remote server this problem occurs.
Since you're using Path.Combine I would suggest passing each part of the path as a parameter. So instead of #"wwwroot\images\materials" as one parameter, you would pass them separately "wwwroot", "images", "materials".
Try this simple. In this you have to inject _hostingEnvironment so you can get ContentRootPath
string folderName = "Upload/Profile/" + user.Id;
string webRootPath = _hostingEnvironment.ContentRootPath;
string newPath = Path.Combine(webRootPath, folderName);
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
string extention = file.ContentType.Split("/")[1];
string fileName = user.Id + ".jpg";
string fullPath = Path.Combine(newPath, fileName);
string envpath = folderName + "/" + fileName;
using (var stream = new FileStream(fullPath, FileMode.Create))
{
file.CopyTo(stream);
}
I have an Azure App (.Net 4.5) and I have some static files stored on the filesystem that I want to read from, but I get a System.UnauthorizedAccessException like so
string template = string.Empty;
var file = HostingEnvironment.MapPath("~/App_Data/EmailTemplates/" + fileName);
if (!string.IsNullOrEmpty(file))
{
template = File.ReadAllText(file); <-- Unauthorized Access Exception Here
}
return template;
I know the best practice is Azure Storage, but how do I make this work this way?
As File.ReadAllText states about UnauthorizedAccessException, it could be caused by one of the following conditions:
path specified a file that is read-only.
-or-
This operation is not supported on the current platform.
-or-
path specified a directory.
-or-
The caller does not have the required permission.
You could leverage kudu console and use Attrib command to check the attributes for your files or directories. Also, you could try to use TYPE command to display the contents of your file or click the Edit button from the file list table as follows:
Also, I created a new web app and deployed my MVC application for displaying the files under the App_Data folder, it could work as expected, you could refer to it.
UPDATE:
//method for getting files
public List<DownLoadFileInformation> GetFiles()
{
List<DownLoadFileInformation> lstFiles = new List<DownLoadFileInformation>();
DirectoryInfo dirInfo = new DirectoryInfo(HostingEnvironment.MapPath("~/App_Data"));
int i = 0;
foreach (var item in dirInfo.GetFiles())
{
lstFiles.Add(new DownLoadFileInformation()
{
FileId = i + 1,
FileName = item.Name,
FilePath = dirInfo.FullName + #"\" + item.Name
});
i = i + 1;
}
return lstFiles;
}
//action for downloading a file
public ActionResult Download(string FileID)
{
int CurrentFileID = Convert.ToInt32(FileID);
var filesCol = obj.GetFiles();
string fullFilePath = (from fls in filesCol
where fls.FileId == CurrentFileID
select fls.FilePath).First();
string contentType = MimeMapping.GetMimeMapping(fullFilePath);
return File(fullFilePath, contentType, new FileInfo(fullFilePath).Name);
}
UPDATE2:
public ActionResult ViewOnline(string FileID)
{
int CurrentFileID = Convert.ToInt32(FileID);
var filesCol = obj.GetFiles();
string fullFilePath = (from fls in filesCol
where fls.FileId == CurrentFileID
select fls.FilePath).First();
string text = System.IO.File.ReadAllText(fullFilePath);
return Content(text);
}
I'm making a button that reads a file path then deletes the files within the folder. It's currently deleting the entire directory. Here's my code:
public void deleteFiles(string Server)
{
string output = "\\\\" + Server + "\\F\\Output";
string input = "\\\\" + Server + "\\F\\Input";
string exceptions = "\\\\" + Server + "\\F\\Exceptions";
new System.IO.DirectoryInfo(input).Delete(true);
new System.IO.DirectoryInfo(output).Delete(true);
new System.IO.DirectoryInfo(exceptions).Delete(true);
}
Would just deleting the directory and recreating it work? Or do you want to preserve permissions?
You are calling Delete method on DirectoryInfo, you should call it on FileInfo's instead:
var files = new DirectoryInfo(input).GetFiles()
.Concat(new DirectoryInfo(output).GetFiles())
.Concat(new DirectoryInfo(exceptions).GetFiles());
foreach(var file in files)
file.Delete();
Another way:
var files = Directory.GetFiles(input)
.Concat(Directory.GetFiles(output))
.Concat(Directory.GetFiles(exceptions));
foreach(var file in files)
File.Delete(file);
DirectoryInfo.Delete and Directory.Delete delete empty directories, if you want to delete files you could try this method:
public void DeleteFiles(string path, bool recursive, string searchPattern = null)
{
var entries = searchPattern == null ? Directory.EnumerateFileSystemEntries(path) : Directory.EnumerateFileSystemEntries(path, searchPattern);
foreach(string entry in entries)
{
try
{
FileAttributes attr = File.GetAttributes(entry);
//detect whether its a directory or file
bool isDir = (attr & FileAttributes.Directory) == FileAttributes.Directory;
if(!isDir)
File.Delete(entry);
else if(recursive)
DeleteFiles(entry, true, searchPattern);
}
catch
{
//ignore
}
}
}
What I'm trying to do is to upload a website using FTP in C# (C Sharp). So I need to upload all files and folders within a folder, keeping its structure. I'm using this FTP class: http://www.codeproject.com/Tips/443588/Simple-Csharp-FTP-Class for the actual uploading.
I have come to the conclusion that I need to write a recursive method that goes through every sub-directory of the main directory and upload all files and folders in it. This should make an exact copy of my folder to the FTP. Problem is... I have no clue how to write a method like that. I have written recursive methods before but I'm new to the FTP part.
This is what I have so far:
private void recursiveDirectory(string directoryPath)
{
string[] filePaths = null;
string[] subDirectories = null;
filePaths = Directory.GetFiles(directoryPath, "*.*");
subDirectories = Directory.GetDirectories(directoryPath);
if (filePaths != null && subDirectories != null)
{
foreach (string directory in subDirectories)
{
ftpClient.createDirectory(directory);
}
foreach (string file in filePaths)
{
ftpClient.upload(Path.GetDirectoryName(directoryPath), file);
}
}
}
But its far from done and I don't know how to continue. I'm sure more than me needs to know this! Thanks in advance :)
Ohh and... It would be nice if it reported its progress too :) (I'm using a progress bar)
EDIT:
It might have been unclear... How do I upload a directory including all sub-directories and files with FTP?
Problem Solved! :)
Alright so I managed to write the method myslef. If anyone need it feel free to copy:
private void recursiveDirectory(string dirPath, string uploadPath)
{
string[] files = Directory.GetFiles(dirPath, "*.*");
string[] subDirs = Directory.GetDirectories(dirPath);
foreach (string file in files)
{
ftpClient.upload(uploadPath + "/" + Path.GetFileName(file), file);
}
foreach (string subDir in subDirs)
{
ftpClient.createDirectory(uploadPath + "/" + Path.GetFileName(subDir));
recursiveDirectory(subDir, uploadPath + "/" + Path.GetFileName(subDir));
}
}
It works very well :)
I wrote an FTP classe and also wrapped it in a WinForms user control. You can see my code in the article An FtpClient Class and WinForm Control.
I wrote a reusable class to upload entire directory to an ftp site on windows server, the program also renames the old version of that folder (i use it to upload my windows service program to the server).
maybe some need this:
class MyFtpClient
{
protected string FtpUser { get; set; }
protected string FtpPass { get; set; }
protected string FtpServerUrl { get; set; }
protected string DirPathToUpload { get; set; }
protected string BaseDirectory { get; set; }
public MyFtpClient(string ftpuser, string ftppass, string ftpserverurl, string dirpathtoupload)
{
this.FtpPass = ftppass;
this.FtpUser = ftpuser;
this.FtpServerUrl = ftpserverurl;
this.DirPathToUpload = dirpathtoupload;
var spllitedpath = dirpathtoupload.Split('\\').ToArray();
// last index must be the "base" directory on the server
this.BaseDirectory = spllitedpath[spllitedpath.Length - 1];
}
public void UploadDirectory()
{
// rename the old folder version (if exist)
RenameDir(BaseDirectory);
// create a parent folder on server
CreateDir(BaseDirectory);
// upload the files in the most external directory of the path
UploadAllFolderFiles(DirPathToUpload, BaseDirectory);
// loop trough all files in subdirectories
foreach (string dirPath in Directory.GetDirectories(DirPathToUpload, "*",
SearchOption.AllDirectories))
{
// create the folder
CreateDir(dirPath.Substring(dirPath.IndexOf(BaseDirectory), dirPath.Length - dirPath.IndexOf(BaseDirectory)));
Console.WriteLine(dirPath.Substring(dirPath.IndexOf(BaseDirectory), dirPath.Length - dirPath.IndexOf(BaseDirectory)));
UploadAllFolderFiles(dirPath, dirPath.Substring(dirPath.IndexOf(BaseDirectory), dirPath.Length - dirPath.IndexOf(BaseDirectory))
}
}
private void UploadAllFolderFiles(string localpath, string remotepath)
{
string[] files = Directory.GetFiles(localpath);
// get only the filenames and concat to remote path
foreach (string file in files)
{
// full remote path
var fullremotepath = remotepath + "\\" + Path.GetFileName(file);
// local path
var fulllocalpath = Path.GetFullPath(file);
// upload to server
Upload(fulllocalpath, fullremotepath);
}
}
public bool CreateDir(string dirname)
{
try
{
WebRequest request = WebRequest.Create("ftp://" + FtpServerUrl + "/" + dirname);
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Proxy = new WebProxy();
request.Credentials = new NetworkCredential(FtpUser, FtpPass);
using (var resp = (FtpWebResponse)request.GetResponse())
{
if (resp.StatusCode == FtpStatusCode.PathnameCreated)
{
return true;
}
else
{
return false;
}
}
}
catch
{
return false;
}
}
public void Upload(string filepath, string targetpath)
{
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential(FtpUser, FtpPass);
client.Proxy = null;
var fixedpath = targetpath.Replace(#"\", "/");
client.UploadFile("ftp://" + FtpServerUrl + "/" + fixedpath, WebRequestMethods.Ftp.UploadFile, filepath);
}
}
public bool RenameDir(string dirname)
{
var path = "ftp://" + FtpServerUrl + "/" + dirname;
string serverUri = path;
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
request.Method = WebRequestMethods.Ftp.Rename;
request.Proxy = null;
request.Credentials = new NetworkCredential(FtpUser, FtpPass);
// change the name of the old folder the old folder
request.RenameTo = DateTime.Now.ToString("yyyyMMddHHmmss");
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
using (var resp = (FtpWebResponse)request.GetResponse())
{
if (resp.StatusCode == FtpStatusCode.FileActionOK)
{
return true;
}
else
{
return false;
}
}
}
catch
{
return false;
}
}
}
Create an instance of that class:
static void Main(string[] args)
{
MyFtpClientftp = new MyFtpClient(ftpuser, ftppass, ftpServerUrl, #"C:\Users\xxxxxxxxxxx");
ftp.UploadDirectory();
Console.WriteLine("DONE");
Console.ReadLine();
}
Unless you're doing this for fun or self-improvement, use a commercial module. I can recommend one from Chilkat, but I'm sure there are others.
Note: I'm pretty sure this does answer the stated problem, What I'm trying to do is to upload a website using FTP in C# (C Sharp).