Copy file from the obtained path to a domain - c#

Hi all is it possible to copy a file from the path obtained to the domain, I tried as follows but I am getting an exception as uri formats are not supported.. So can some one help me how to copy the file
string filePath = "D:\\Folder\\filename.jpg";
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo.Exists)
{
path = "http://WWW.somedomain.com";
string temppath = path + "/Temp" + "/" + fileInfo.Name;
if (!File.Exists(temppath))
{
var uri = new Uri(temppath);
File.Copy(filePath, uri.AbsoluteUri);
}

You want to check the existence of file on the server. This is not possible using File.Exist method as it doesn't supports the URI. This method expect the relative path and checked the existence on machine (physical location).
In this case you should use WebRequest and get the response from the server. If server returns 404 then your file doesn't exist on the serve or you can check the Content Length.
WebRequest request = WebRequest.Create(new Uri(temppath));
request.Method = "HEAD";
WebResponse response = request.GetResponse()
var contentLength = response.ContentLength;
if (contentLength < 0)
{
// file doesn't exist.
}

Related

FtpWebRequest returning "550 File unavailable (e.g. file not found, no access)" when using ListDirectoryDetails for a directory that exists

I have an annoying problem preventing me to get a file I need in an FTP. This file may have differents names so I need to access the folder first and list files inside to do a request directly to the file then.
My problem is that I can access this file in Filezilla for example, and perfectly discovers the folder as well, but when using an FtpWebResponse instance to get the folder, I have an error 550
550 File unavailable (e.g. file not found, no access)
here is the code :
FtpWebRequest wr = (FtpWebRequest)WebRequest.Create("ftp://ftp.dachser.com/data/edi/kunden/da46168958/out");
wr.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
wr.Credentials = new NetworkCredential("login", "password");
FtpWebResponse response = (FtpWebResponse)wr.GetResponse();
Stream reponseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(reponseStream);
string names = reader.ReadToEnd();
FtpWebResponse response = (FtpWebResponse)wr.GetResponse();
is the line throwing the error
PS: Production, tests and FileZilla are on the same domain, using the same internet connection (if it helps)
Thanks for your attention and feedback
The FileZilla logs:
Logs from my program, error circled in red isn't related to FTP error
When FtpWebRequest interprets the URL, it does not consider the slash that separates the hostname and the path as a part of the path. The extracted path is then used with FTP CWD command as is. That means that the FTP server will resolve the path relatively to your home directory. If your account is not chrooted (the home is not seen as the root by the client), the lack of the leading slash leads to unexpected behaviour.
In your case, you start in /remote/path and with URL like ftp://example.com/remote/path/, it will try to change to remote/path, so ultimately to /remote/path/remote/path. That's not what you want.
Either you must use a relative path to the home folder. What in your case means using an URL without any path.
Or use an absolute path, for which you need to use two slashes after the hostname: ftp://example.com//remote/path/.
Also note that an URL to a folder should end with a slash: Why does FtpWebRequest return an empty stream for this existing directory?
For other 550 problems, see FtpWebRequest returns error 550 File unavailable
In 2021 this works on both our Linux and Windows live boxes reading from ftp server (both on Windows and Linux)
Note
the main folder on the Windows ftp is web
the main folder on the Linux ftp is public_html
TL;DR;
bottom line: the URL needs to be ended with /
It works:
ftp://ftp.yourdomain.com.br/public_html/
ftp://ftp.yourdomain.com.br//public_html/
ftp://ftp.yourdomain.com.br/web/
ftp://ftp.yourdomain.com.br//web/
It doesn't work:
ftp://ftp.yourdomain.com.br/public_html
ftp://ftp.yourdomain.com.br//public_html
ftp://ftp.yourdomain.com.br/web
ftp://ftp.yourdomain.com.br//web
Usage:
//verifiy if the directory public_html does exists
var url = "/public_html/";
var result = FtpUtil.DoesDirectoryExists(url, "ftp://ftp.yourdomain.com.br", "ftp user here", "ftp password here");
static bool DoesDirectoryExists(string directory, string ftpHost, string ftpUser, string ftpPassword) {
FtpWebRequest ftpRequest = null;
try {
ftpRequest = (FtpWebRequest)WebRequest.Create(new Uri("ftp://" + ftpHost + directory));
ftpRequest.Credentials = new NetworkCredential(ftpUser, string ftpPassword);
ftpRequest.UseBinary = true;// optional
ftpRequest.KeepAlive = false;// optional
ftpRequest.UsePassive = true;// optional
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
using (FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse()) {
return true;//directory found
}
}
catch (WebException ex) {
if (ex.Response != null) {
FtpWebResponse response = (FtpWebResponse)ex.Response;
if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
return false;// directory not found.
}
return false; // directory not found.
}
finally {
ftpRequest = null;
}
}

FTP file uploaded to ASP page

I have seen some answers similar to my question but still could not figure out.
I am using the code below for a user to upload an MP3 file (I am using FTP) and it worked fine with local host (simple WinForm app) but it threw the error when using remote server (remote DNN site):
System.IO.FileNotFoundException: Could not find file 'C:\Windows\SysWOW64\inetsrv\Test.mp3'.
I know that if the test.mp3 file is in this server location then it should work but it was actually in my C:\Temp\Test.mp3 path. I think the FileUpload1 did not give the correct file path. How can I fix this?
protected void btnUpload_Click(object sender, EventArgs e)
{
string url = System.Configuration.ConfigurationManager.AppSettings["FTPUrl"].ToString();
string username = System.Configuration.ConfigurationManager.AppSettings["FTPUserName"].ToString();
string password = System.Configuration.ConfigurationManager.AppSettings["FTPPassWord"].ToString();
string filePath = FileUpload1.PostedFile.FileName;
if (filePath != String.Empty)
UploadFileToFtp(url, filePath, username, password);
}
public static void UploadFileToFtp(string url, string filePath, string username, string password)
{
var fileName = Path.GetFileName(filePath);
var request = (FtpWebRequest)WebRequest.Create(url + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(username, password);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
using (var fileStream = File.OpenRead(filePath))
{
using (var requestStream = request.GetRequestStream())
{
fileStream.CopyTo(requestStream);
requestStream.Close();
}
}
var response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload done: {0}", response.StatusDescription);
response.Close();
}
The HttpPostedFile.FileName is a "fully qualified name of the file on the client".
And I believe most web browsers actually provide a file name only, without any path. So you get Test.mp3 only, and when you try to use such "relative" path locally on the server, it gets resolved to a current working directory of the web server, what is the C:\Windows\SysWOW64\inetsrv.
Instead, access an uploaded contents directly using HttpPostedFile.InputStream (copy that to GetRequestStream).
See HttpPostedFile documentation.

Howto: download a file keeping the original name in C#?

I have files on a server that can be accessed from a URL formatted like this:
http:// address/Attachments.aspx?id=GUID
I have access to the GUID and need to be able to download multiple files to the same folder.
if you take that URL and throw it in a browser, you will download the file and it will have the original file name.
I want to replicate that behavior in C#. I have tried using the WebClient class's DownloadFile method, but with that you have to specify a new file name. And even worse, DownloadFile will overwrite an existing file. I know I could generate a unique name for every file, but i'd really like the original.
Is it possible to download a file preserving the original file name?
Update:
Using the fantastic answer below to use the WebReqest class I came up with the following which works perfectly:
public override void OnAttachmentSaved(string filePath)
{
var webClient = new WebClient();
//get file name
var request = WebRequest.Create(filePath);
var response = request.GetResponse();
var contentDisposition = response.Headers["Content-Disposition"];
const string contentFileNamePortion = "filename=";
var fileNameStartIndex = contentDisposition.IndexOf(contentFileNamePortion, StringComparison.InvariantCulture) + contentFileNamePortion.Length;
var originalFileNameLength = contentDisposition.Length - fileNameStartIndex;
var originalFileName = contentDisposition.Substring(fileNameStartIndex, originalFileNameLength);
//download file
webClient.UseDefaultCredentials = true;
webClient.DownloadFile(filePath, String.Format(#"C:\inetpub\Attachments Test\{0}", originalFileName));
}
Just had to do a little string manipulation to get the actual filename. I'm so excited. Thanks everyone!
As hinted in comments, the filename will be available in Content-Disposition header. Not sure about how to get its value when using WebClient, but it's fairly simple with WebRequest:
WebRequest request = WebRequest.Create("http://address/Attachments.aspx?id=GUID");
WebResponse response = request.GetResponse();
string originalFileName = response.Headers["Content-Disposition"];
Stream streamWithFileBody = response.GetResponseStream();

Get Binary File List from Remote server

I'm developing a system that need to download binary files from a server folder. In here I will check before downloading whether they are in my local folder.so I need to get list of the *.bin files.
I have tried code in below, but it generate list all the files that on server folder.
private string[] GetRemoteFileList()
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(_remoteHost));
request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
request.Method = WebRequestMethods.Ftp.ListDirectory;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
string FileNames = reader.ReadToEnd();
string[] Files = Regex.Split(FileNames, "\r\n");
return Files;
}
What I need is filter out only *.bin files. How can I achieve this?
What have you tried?
You have now in Files an array of all files in the current directory. Why don't you filter that list? For example:
return Files.Where(
f => f.EndsWith(".bin", StringComparison.OrdinalIgnoreCase)
).ToList();

FTP Check if file exist when Uploading and if it does rename it in C#

I have a question about Uploading to a FTP with C#.
What I want to do is if the file exists then I want to add like Copy or a 1 after the filename so it doesn't replace the file. Any Ideas?
var request = (FtpWebRequest)WebRequest.Create(""+destination+file);
request.Credentials = new NetworkCredential("", "");
request.Method = WebRequestMethods.Ftp.GetFileSize;
try
{
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
FtpWebResponse response = (FtpWebResponse)ex.Response;
if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
{
}
}
It's not particularly elegant as I just threw it together, but I guess this is pretty much what you need?
You just want to keep trying your requests until you get a "ActionNotTakenFileUnavailable", so you know your filename is good, then just upload it.
string destination = "ftp://something.com/";
string file = "test.jpg";
string extention = Path.GetExtension(file);
string fileName = file.Remove(file.Length - extention.Length);
string fileNameCopy = fileName;
int attempt = 1;
while (!CheckFileExists(GetRequest(destination + "//" + fileNameCopy + extention)))
{
fileNameCopy = fileName + " (" + attempt.ToString() + ")";
attempt++;
}
// do your upload, we've got a name that's OK
}
private static FtpWebRequest GetRequest(string uriString)
{
var request = (FtpWebRequest)WebRequest.Create(uriString);
request.Credentials = new NetworkCredential("", "");
request.Method = WebRequestMethods.Ftp.GetFileSize;
return request;
}
private static bool checkFileExists(WebRequest request)
{
try
{
request.GetResponse();
return true;
}
catch
{
return false;
}
}
Edit: Updated so this will work for any type of web request and is a little slimmer.
Since FTP control protocol is slow in nature (send-receive) I suggest first pulling directory content and checking against it before uploading the file. Note that dir can return two different standards: dos and unix
Alternatively you can use the MDTM file command to check if file already exist (used to retrieve timestamp of a file).
There is no shortcut. You need to dir the target directory then use # to determine which name you want to use.
I am working on something similar. My problem was that:
request.Method = WebRequestMethods.Ftp.GetFileSize;
was not really working. Sometimes it gave exception sometimes it didn't. And for the same file! Have no idea why.
I change it as Tedd said (thank you, btw) to
request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
and it seems to work now.

Categories

Resources