Cannot make new directories in FTP (C#) - c#

I was trying to upload a file to my FTP server (EC2) via a simple C# windows application I made.
Problem I'm Having : If the directory already exists, I can make a file inside it. However, if the directory doesn't exist, I cannot make a directory.
What I Checked : I double checked the write permissions. I logged in via WinSCP and I can make new directories in there without any problems. I've given the user privileges.
My Code :
private async void FileFTPUpload(string sourcefilepath, string folderPath) {
String ftpurl = #"ftp://xx.xxx.xxx.xxx/" + "trial/12/1.txt";
Console.WriteLine("Ftp url : " + ftpurl);
String ftpusername = "myUserName";
String ftppassword = "myPassword";
try {
string filename = Path.GetFileName(sourcefilepath);
string ftpfullpath = ftpurl;
WebRequest ftp = WebRequest.Create(ftpurl);
ftp.Method = WebRequestMethods.Ftp.MakeDirectory;
ftp.Credentials = new NetworkCredential(ftpusername, ftppassword);
ftp.Method = WebRequestMethods.Ftp.UploadFile;
FileStream fs = File.OpenRead(sourcefilepath);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream ftpstream = ftp.GetRequestStream();
ftpstream.Write(buffer, 0, buffer.Length);
ftpstream.Close();
} catch (Exception ex) {
Console.WriteLine("Exception Occurred : " + ex);
//throw ex;
}
}
Now, if the "trial/12/" exists, then 1.txt will be made. Otherwise, I get the error :
System.Net.WebException: The remote server returned an error: (553) File name not allowed.
I'm not sure what's happening and what's not. Could use some assistance.
Thank You.
EDIT : When I do this :
String ftpurl = #"ftp://xx.xxx.xxx.xxx/" + "trial";
It doesn't make a directory. I just makes a file named "trial".
Doing This :
String ftpurl = #"ftp://xx.xxx.xxx.xxx/" + "trial/";
Gives that same error 553

You will have to seperate your code into two requests. The first should create the directory and the second upload the file.
var filePath = #"ftp://xx.xxx.xxx.xxx/trial/12/1.txt";
var credentials = new NetworkCredential(ftpusername, ftppassword);
{
// create directory
var directoryPath = Path.GetDirectoryName(filePath);
var request = WebRequest.Create(directoryPath);
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Credentials = credentials;
using(var response = (FtpWebResponse)requestDir.GetResponse())
{
// TODO: handle errors
}
}
{
// upload file
using (WebClient client = new WebClient())
{
client.Credentials = credentials;
client.UploadFile(filePath, "STOR", sourcefilepath);
}
}

Related

ftpwebrequest.getresponse is throwing 550 access denied

I am trying to figure out how to get this file uploaded to my ftp server in C#. When it calls getResponse() on ftpwebrequest it is throwing an error that says "550 - access denied". I cannot figure out why. I can connect to the server with Filezilla just fine using the same credentials.
Here is my code that does the connection:
private void UploadFileToFTP(HttpPostedFile file, string server, string user, string pass)
{
string uploadUrl = server + file.FileName;
string uploadFileName = Path.GetFileName(file.FileName);
Stream streamObj = file.InputStream;
Byte[] buffer = new Byte[file.ContentLength];
streamObj.Read(buffer, 0, buffer.Length);
streamObj.Close();
streamObj = null;
try
{
SetMethodRequiresCWD();
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(uploadUrl);
//ftp.Method = WebRequestMethods.Ftp.MakeDirectory;
ftp.Method = WebRequestMethods.Ftp.UploadFile;
ftp.UsePassive = true;
ftp.Credentials = new NetworkCredential(user, pass);
FtpWebResponse CreateForderResponse = (FtpWebResponse)ftp.GetResponse();
if (CreateForderResponse.StatusCode == FtpStatusCode.PathnameCreated)
{
string ftpUrl = string.Format("{0}/{1}", uploadUrl, uploadFileName);
FtpWebRequest requestObj = FtpWebRequest.Create(ftpUrl) as FtpWebRequest;
requestObj.KeepAlive = true;
requestObj.UseBinary = true;
requestObj.Method = WebRequestMethods.Ftp.UploadFile;
requestObj.Credentials = new NetworkCredential(user, pass);
Stream requestStream = requestObj.GetRequestStream();
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Flush();
requestStream.Close();
requestObj = null;
}
}
catch (WebException e)
{
String status = ((FtpWebResponse)e.Response).StatusDescription;
}
}
OK, I tinkered around with this some more after reading through the comments here. I went into my Kaspersky settings and disabled scanning of port 20 and 21. Boom! File is there. Now it is coming across empty for some reason, so I will investigate that or come back for some help here! :)

Check whether a folder exists on FTP server before uploading to that folder

I've checked other posts on this topic, but I can't seem to figure out the fundamentals of checking whether or not a directory exists on an FTP server before trying to upload a file there.
With the following code I get an exception when trying to upload to a folder that already exists. I feel that it shouldn't be too hard to just use some kind of folder.Exists before creating the directory, but I can't get it to work. Any ideas?
Upload method as of now:
String id = Request.QueryString["ID"];
String path = Server.MapPath("~/temp/");
String filename = Path.GetFileName(fuPicture.PostedFile.FileName);
if (fuPicture.HasFile)
{
try
{
fuPicture.PostedFile.SaveAs(path + fuPicture.FileName);
}
catch (Exception ex)
{
lblFeedback.Text = "Fel vid uppladdning";
}
path += fuPicture.FileName;
String ftpServer = "ftp://xxx";
String userName = "xx";
String password = "xx";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri("ftp://xx/" + id));
// I want to implement an if-condition here
// whether or not the folder exists
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Credentials = new NetworkCredential(userName, password);
using (var resp = (FtpWebResponse)request.GetResponse())
{
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(userName, password);
client.UploadFile(ftpServer + "/" + id + "/" + new FileInfo(path).Name, "STOR", path);
resp.Close();
}
Try listing directory ListDirectory, if not found then create MakeDirectory
request.Method = WebRequestMethods.Ftp.ListDirectory;
request.Credentials = new NetworkCredential(userName, password);
try
{
using (request.GetResponse())
{
//continue
}
}
catch (WebException)
{
request.Method = WebRequestMethods.Ftp.MakeDirectory;
using (request.GetResponse())
{
//continue
}
}

Save file to ftp server

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

How to upload a file in a non-default directory using FTPWEBREQUEST?

I face an issue while I try to upload a file in a non-default directory of the server.
When I use "ftp://server01/autofile/test.zip", the file gets uploaded without any issues since autofile is the default directory.
But when I use the below code, I get an exception which says "The remote server returned an error: (550) File unavailable (e.g., file not found, no access).". Shown below is the piece of code I use.
string inputfilepath = "E:\\Test\\test.ZIP";
string ftpfullpath = "ftp://server01/../bcp/ftp/ftpsftiu/test.ZIP";
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpfullpath);
ftp.Method = WebRequestMethods.Ftp.UploadFile;
ftp.Credentials = new NetworkCredential("Username", "password");
ftp.UsePassive = true;
ftp.KeepAlive = true;
ftp.UseBinary = true;
FileStream fs = File.OpenRead(inputfilepath);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream reqStream = ftp.GetRequestStream();
But I can open the above non-default directory path(ftp://server01/../bcp/ftp/ftpsftiu/test.ZIP) through the Run Command of windows.
How do I upload my file to this non-default directory of the server through C# code?
please help me to fix this.
Thanks in advance!!!
With regards,
Shadu
It worked for me if I put another slash after the server (//server//).
I did (also) fully qualify the output path name.
The static GetCread() is a method call into a home-grown class.
Example:
static void Main(string[] args)
{
string strSystem = "MAPS";
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://" + strSystem +"//export/home/hinest/science/trans/fred.txt");
req.Credentials = CGetCred.GetCred(strSystem);
req.Method = WebRequestMethods.Ftp.UploadFile;
FtpWebResponse resp = (FtpWebResponse)req.GetResponse();
StreamWriter fileOut = new StreamWriter(req.GetRequestStream());
StreamReader fileIn = new StreamReader(#"c:\science\"+strSystem+".txt");
while (!fileIn.EndOfStream)
{
fileOut.WriteLine(fileIn.ReadLine());
}
fileIn.Close();
fileOut.Close();
resp.Close();
}

Unable to rename file with ftp methods when current user directory is different from root

Remark: due to spam prevention mechanizm I was forced to replace the beginning of the Uris from ftp:// to ftp.
I've got following problem. I have to upload file with C# ftp method and afterwards rename it. Easy, right? :)
Ok, let's say my ftp host is like this:
ftp.contoso.com
and after logging in, current directory is set to:
users/name
So, what I'm trying to achieve is to log in, upload file to current directory as file.ext.tmp and after upload is successful, rename the file to file.ext
The whole difficulty is, as I guess, to properly set the request Uri for FtpWebRequest.
MSDN states:
The URI may be relative or absolute. If the URI is of the form "ftp://contoso.com/%2fpath" (%2f is an escaped '/'), then the URI is absolute, and the current directory is /path. If, however, the URI is of the form "ftp://contoso.com/path", first the .NET Framework logs into the FTP server (using the user name and password set by the Credentials property), then the current directory is set to UserLoginDirectory/path.
Ok, so I upload file with the following URI:
ftp.contoso.com/file.ext.tmp
Great, the file lands where I wanted it to be: in directory "users/name"
Now, I want to rename the file, so I create web request with following Uri:
ftp.contoso.com/file.ext.tmp
and specify rename to parameter as:
file.ext
and this gives me 550 error: file not found, no permissions, etc.
I traced this in Microsoft Network Monitor and it gave me:
Command: RNFR, Rename from
CommandParameter: /file.ext.tmp
Ftp: Response to Port 53724, '550 File /file.ext.tmp not found'
as if it was looking for the file in the root directory - not in the current directory.
I renamed the file manually using Total Commander and the only difference was that CommandParameter was without the first slash:
CommandParameter: file.ext.tmp
I'm able to successfully rename the file by supplying following absolute URI:
ftp.contoso.com/%2fusers/%2fname/file.ext.tmp
but I don't like this approach, since I would have to know the name of current user's directory. It can probably be done by using WebRequestMethods.Ftp.PrintWorkingDirectory, but it adds extra complexity (calling this method to retrieve directory name, then combining the paths to form proper URI).
What I don't understand is why the URI ftp.contoso.com/file.ext.tmp is good for upload and not for rename? Am I missing something here?
The project is set to .NET 4.0, coded in Visual Studio 2010.
Edit
Ok, I place code snippet.
Please note that ftp host, username and password should be filled out. For this sample to work - that is, produce an error - user directory must be different from root ("pwd"-command should return something different than "/")
class Program
{
private const string fileName = "test.ext";
private const string tempFileName = fileName + ".tmp";
private const string ftpHost = "127.0.0.1";
private const string ftpUserName = "anonymous";
private const string ftpPassword = "";
private const int bufferSize = 524288;
static void Main(string[] args)
{
try
{
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
if (!File.Exists(path))
File.WriteAllText(path, "FTP RENAME SAMPLE");
string requestUri = "ftp://" + ftpHost + "/" + tempFileName;
//upload
FtpWebRequest uploadRequest = (FtpWebRequest)WebRequest.Create(requestUri);
uploadRequest.UseBinary = true;
uploadRequest.UsePassive = true;
uploadRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
uploadRequest.KeepAlive = true;
uploadRequest.Method = WebRequestMethods.Ftp.UploadFile;
Stream requestStream = null;
FileStream localFileStream = null;
localFileStream = File.OpenRead(path);
requestStream = uploadRequest.GetRequestStream();
byte[] buffer = new byte[bufferSize];
int readCount = localFileStream.Read(buffer, 0, bufferSize);
long bytesSentCounter = 0;
while (readCount > 0)
{
requestStream.Write(buffer, 0, readCount);
bytesSentCounter += readCount;
readCount = localFileStream.Read(buffer, 0, bufferSize);
System.Threading.Thread.Sleep(100);
}
localFileStream.Close();
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)uploadRequest.GetResponse();
FtpStatusCode code = response.StatusCode;
string description = response.StatusDescription;
response.Close();
if (code == FtpStatusCode.ClosingData)
Console.WriteLine("File uploaded successfully");
//rename
FtpWebRequest renameRequest = (FtpWebRequest)WebRequest.Create(requestUri);
renameRequest.UseBinary = true;
renameRequest.UsePassive = true;
renameRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
renameRequest.KeepAlive = true;
renameRequest.Method = WebRequestMethods.Ftp.Rename;
renameRequest.RenameTo = fileName;
try
{
FtpWebResponse renameResponse = (FtpWebResponse)renameRequest.GetResponse();
Console.WriteLine("Rename OK, status code: {0}, rename status description: {1}", response.StatusCode, response.StatusDescription);
renameResponse.Close();
}
catch (WebException ex)
{
Console.WriteLine("Rename failed, status code: {0}, rename status description: {1}", ((FtpWebResponse)ex.Response).StatusCode,
((FtpWebResponse)ex.Response).StatusDescription);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
Console.ReadKey();
}
}
}
I have encountered a similar issue. The problem is that FtpWebRequest (incorrectly) prepends '/' to rename requests, as can be seen from this log (upload & rename):
URL:
http://127.0.0.1/Test.txt
FTP log:
STOR Test.txt.part
RNFR /Test.txt.part
RNTO /Test.txt
Please note that this problem occurs only when you are uploading to the root directory. If you changed the URL to http://127.0.0.1/path/Test.txt, then everything would work fine.
My solution to this problem is to use %2E (dot) as the path:
URL:
http://127.0.0.1/%2E/Test.txt
FTP log:
STOR ./Test.txt.part
RNFR ./Test.txt.part
RNTO ./Test.txt
You have to url-encode the dot, otherwise FtpWebRequest would simplify the path "/./" to "/".
C#
using System.Net;
using System.IO;
Rename Filename on FTP Server function
C#
private void RenameFileName(string currentFilename, string newFilename)
{
FTPSettings.IP = "DOMAIN NAME";
FTPSettings.UserID = "USER ID";
FTPSettings.Password = "PASSWORD";
FtpWebRequest reqFTP = null;
Stream ftpStream = null ;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + FTPSettings.IP + "/" + currentFilename));
reqFTP.Method = WebRequestMethods.Ftp.Rename;
reqFTP.RenameTo = newFilename;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(FTPSettings.UserID, FTPSettings.Password);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
ftpStream = response.GetResponseStream();
ftpStream.Close();
response.Close();
}
catch (Exception ex)
{
if (ftpStream != null)
{
ftpStream.Close();
ftpStream.Dispose();
}
throw new Exception(ex.Message.ToString());
}
}
public static class FTPSettings
{
public static string IP { get; set; }
public static string UserID { get; set; }
public static string Password { get; set; }
}

Categories