I used the following example code to upload to an FTP, it turns out that the server don't want to use anonymous connection, but I can't figure out how to change it to be able to upload with out breaking that rule.
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/" + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential("username", "password");
// Copy the contents of the file to the request stream.
byte[] fileContents;
using (StreamReader sourceStream = new StreamReader(file))
{
fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
}
request.ContentLength = fileContents.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(fileContents, 0, fileContents.Length);
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
}
Anonymous credentials are still credentials. You can get rid of them by removing the line
request.Credentials = new NetworkCredential("username", "password");
and you won't be sending any credentials to the server at all.
Nevertheless, as mentioned in "Remarks" section of the MSDN docs, FtpWebRequest class is not recommended to be used for new development. Microsoft recommends to use one of third-party libraries listed here.
I also recommend choosing one of those, as they provide more robust way to communicate with FTP servers. You can enable logging and it will be easier for you to see why exactly your communication with the server is failing. You will see all the commands your app is sending to the server and also all the responses from the server. These libraries also implement all the basic operations like listing, downloading, uploading, permission setting, sync/async etc, so you don't have to write them yourself.
Related
I need some guidance. I need to develop a customizable FTP in C# that should be configured using App.Config file. Also, the FTP should push the data to any server from any client again depends on config file.
I will appreciate if someone can guide, if there is any API or any other useful suggestion, or move me in the right direction.
You can use FtpWebRequest; however, this is fairly low level. There is a higher-level class WebClient, which requires much less code for many scenarios; however, it doesn't support FTP/SSL by default. Fortunately, you can make WebClient work with FTP/SSL by registering your own prefix:
private void RegisterFtps()
{
WebRequest.RegisterPrefix("ftps", new FtpsWebRequestCreator());
}
private sealed class FtpsWebRequestCreator : IWebRequestCreate
{
public WebRequest Create(Uri uri)
{
FtpWebRequest webRequest = (FtpWebRequest)WebRequest.Create(uri.AbsoluteUri.Remove(3, 1)); // Removes the "s" in "ftps://".
webRequest.EnableSsl = true;
return webRequest;
}
}
Once you do this, you can use WebClient almost like normal, except that your URIs start with "ftps://" instead of "ftp://". The one caveat is that you have to specify the method parameter, since there won't be a default one. E.g.
using (var webClient = new WebClient()) {
// Note here that the second parameter can't be null.
webClient.UploadFileAsync(uploadUri, WebRequestMethods.Ftp.UploadFile, fileName, state);
}
The accepted answer works, indeed. But I find it too cumbersome to register a prefix, implement an interface, and all that stuff, particularly, if you need it just for one transfer.
FtpWebRequest is not that difficult to use. So I believe that for one-time use, it's better to go this way:
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.EnableSsl = true;
request.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(#"C:\local\path\file.zip"))
using (Stream ftpStream = request.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
The key is the EnableSsl property.
For other scenarios, see:
Upload and download a binary file to/from FTP server in C#/.NET
We use edtFTPnet with good results.
I'm trying to write a c# code that downloads the kml file from https://maps.google.com/locationhistory/b/0
I wrote the following code, but the http response I get back brings me to the login page even though
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://maps.google.com/locationhistory/b/0/kml?startTime=1373666400000&endTime=1373752800000");
request.Credentials = new NetworkCredential("username", "password");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Get the stream associated with the response.
Stream receiveStream = response.GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
using (StreamWriter outfile = new StreamWriter(#"temp.kml"))
{
outfile.Write(readStream.ReadToEnd());
}
response.Close();
readStream.Close();
I try to pass the user credentials.
I already tried these solutions :
- How to use HttpWebRequest.Credentials Property for Basic Authentication?
- C# HttpWebRequest using Basic authentication
but nothing worked.
Does anybody knows how to pass the google credentials, and has experienced google location history api?
Thanks!
I just purchased some online storage from GoDaddy and I an trying to FTP into my storage account. The thing is, I can view and modify my account using FileZilla, but my C Sharp program will not even access it because of the "hostname could not be parsed" error.
I believe it is because the entire ftp address of my account has two "#" signs in the url, and it is the wreaking havoc in the URI creation process.
Is there anyway I can get around this, or am I screwed because of the naming convention of the GoDaddy storage?
The URL is: ftp:[slashslash]lastname.firstname#gmail.com#onlinefilefolder.com/Home/
Do you need to specify the username and password in the URI for some specific reason? You can simply connect to the host and then provide credentials.
// Create a request to the host
var request = (FtpWebRequest)WebRequest.Create("ftp://onlinefilefolder.com");
// Set the username and password to use
request.Credentials = new NetworkCredential ("lastname.firstname#gmail.com","password");
request.Method = WebRequestMethods.Ftp.UploadFile;
var sourceStream = new StreamReader("testfile.txt");
var fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
response.Close();
The exception is originating from System.Uri, which (despite it being acceptable by the standards definition) will not allow two # symbols.
// This will reproduce the reported exception, I assume it is what your code is
// doing either explicitly, or somewhere internally
new Uri(#"ftp://lastname.firstname#gmail.com#onlinefilefolder.com/Home/")
A potential workaround is to percent-encode the first # symbol, which will allow the Uri instance to be instantiated without exception--but may or may not work depending on the server's behavior (I have only used this approach a couple times, but it has worked for me):
new Uri(#"ftp://lastname.firstname%40gmail.com#onlinefilefolder.com/Home/")
I have the following code to retrieve a file via FTP:
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath);
request.KeepAlive = true;
request.UsePassive = true;
request.UseBinary = true;
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(username, password);
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
using (StreamWriter destination = new StreamWriter(destinationFile))
{
destination.Write(reader.ReadToEnd());
destination.Flush();
}
return 0;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
This works in most cases, but I have one client machine where I get an exception:
The remote server returned an error 403: Forbidden
Can anyone tell me why this could be the case? It’s exactly the same code running on all clients (including the same username and password)?
I've encountered the same problem.
I have already done some monitoring.
First I monitored communications for FTP connection via TotalCommander (It works, so it is a good reference). After that I also monitored my program. I was shocked by what was happening.
Somehow HTTP request was sent by an FTPRequest instance! I haven't solved the problem yet, but I am getting closer. I'll inform you if I find out anything new yet.
The solution was very simple for me. I just added the following line, after creating the request instance:
request.Proxy = null;
The only thing I can suggest is installing Wireshark and monitoring exactly what's being transmitted between the client and server, and comparing that between different machines. If necessary, to get the messages more similar between FTP and IE, change the request's user agent. Is there any funky networking going on, like IP-based permissions?
I'm attempting to use Fogbugz's BugzScout in order to automatically submit unhanded application exceptions to my Fogbugz on demand Account. I've written up a wrapper class for it and everything appears to be just groovy - on my box. Testing the same code in the production environment, behind a Proxy that requires authentication, I have had nothing but issues.
I went to work modifying the BugzScout code in order to get it to authenticate with the Proxy, and after trying many different methods suggested via a Google search, found one that works! But now I'm getting an "Connection actively refused" error from Fogbugz itself, and I don't know what to do.
Here is the code where the BugzScout connects via a .net WebClient to submit a new case, with my modifications to deal with our Proxy. What am I doing that would cause Fogbugz to refuse my request? I've removed all non web-client related code from the procedure for ease of reading.
public string Submit(){
WebClient client = new WebClient();
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Byte[] response = client.DownloadData(fogBugzUrl);
string responseText = System.Text.Encoding.UTF8.GetString(response);
return (responseText == "") ? this.defaultMsg : responseText;
}
The url is correct and the case is filled in properly- this has been verified.
EDIT: Additional info.
Using Fogbugz on Demand.
Using FogBugz.net code in it's entirety, with only these additions
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Error occurs when attempting to connect to both https://oursite.fogbugz.com/scoutsubmit.asp and http://oursite.fogbugz.com//scoutsubmit.asp (except one says port 443, and the other port 80, obviously)
I don't know anything about web authentication so I can't tell you what kind I'm using- if you tell me where to look I'd be happy to answer that for you.
Got the fix from Fogbugz- this is the appropriate network code to get though the proxy authentication and not mis-authenticate with Bugzscout.
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;
WebRequest request = WebRequest.Create(fogBugzUrl);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
Is your fogbugzUrl using HTTP Basic Authentication? Is it SSL (hosted on On Demand?)
The connection actively refused message would be coming from the web server itself, not really FogBugz.
Can you post the HTTP Status Code?
One thing to note if you are using FogBugz On Demand is you HAVE to use the https:// url (not the http url).