NET Framework 4.6
I got a weird and difficult bug inside my code. When i upload a ZIP file; 150MB (slow internet, takes 15 minuten to upload) sometimes the task doesn't 100% complete. It will never get to the last Console line and hangs on the progressbar while loop.
The file on the FTP server is complete and not corrupted. So why does it hang on some files (5 out of the 10 times)?
Tried some posts from other old posts saying that it could be the request config. Also tried to close the ftpStream/fileStream after the while loop. But this won't have any effect.
Hope someone could help me out. This is the Task:
Task TaskA = Task.Run(async () =>
{
// Get filesize
double len = new FileInfo(zipPathFull).Length;
string resultSize = ConvertToReadable(len);
ThreadSafeUpdateStatus(String.Format("Zip bestand aangemaakt, uploaden {0}...", resultSize));
// Verstuur ZIP over FTP
Console.WriteLine("Starting FTP commands...");
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://DOMAIN.nl/domains/DOMAIN.nl/public_html/transfer/zips/" + zipfilename + ".zip");
request.Credentials = new NetworkCredential("USERNAME", "PASSWORD");
request.Timeout = -1;
request.KeepAlive = true;
request.UseBinary = true;
request.UsePassive = true;
request.ServicePoint.ConnectionLimit = 1000;
request.Method = WebRequestMethods.Ftp.UploadFile;
Console.WriteLine("Uploading over FTP...");
using (Stream fileStream = File.OpenRead(zipPathFull))
using (Stream ftpStream = request.GetRequestStream())
{
byte[] buffer = new byte[10240];
int read;
while ((read = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
Console.WriteLine("Buffer status: " + (int)fileStream.Position);
ftpStream.Write(buffer, 0, read);
var percent = 100m * ((decimal)fileStream.Position / fileStream.Length);
double doublepercentage = (double)percent;
ThreadSafeUpdateProgress(doublepercentage);
string CurrentresultSize = ConvertToReadable((double)fileStream.Position);
ThreadSafeUpdateStatus(String.Format("Zip bestand aangemaakt, uploaden {0}/{1}...", CurrentresultSize, resultSize));
}
ftpStream.Close();
fileStream.Close();
}
request.Abort();
Console.WriteLine("FTP Done");
.....
});
Related
I want to download file from FTP and open a download/save prompt in user's web browser, when the user clicks on a download button on ASP.NET C# page.
string strDownloadURL = System.Configuration.ConfigurationSettings.AppSettings["DownloadURL"];
string HostName = System.Configuration.ConfigurationSettings.AppSettings["HostName"];
string strUser = System.Configuration.ConfigurationSettings.AppSettings["BasicAuthenticationUser"];
string strPWD = System.Configuration.ConfigurationSettings.AppSettings["BasicAuthenticationPWD"];
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(HostName + strFile);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(strUser, strPWD);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
string fileName = #"c:\temp\" + strFile + "";
Directory.CreateDirectory(Path.GetDirectoryName(fileName));
FileStream file = File.Create(fileName);
byte[] buffer = new byte[2 * 1024];
int read;
while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0) { file.Write(buffer, 0, read); }
file.Close();
responseStream.Close();
response.Close();
So, assuming you're writing the FTP request's response stream down to the ASP.NET response stream, and want to trigger the download dialog in the browser, you'll want to set the Content-Disposition header in the response.
// note: since you are writing directly to client, I removed the `file` stream
// in your original code since we don't need to store the file locally...
// or so I am assuming
Response.AddHeader("content-disposition", "attachment;filename=" + strFile);
byte[] buffer = new byte[2 * 1024];
int read;
while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0)
{
Response.OutputStream.Write(buffer, 0, read);
}
responseStream.Close();
response.Close();
The answer by #moribvndvs is correct. But the code can be way simpler with use of WebClient.OpenRead and Stream.CopyTo:
var filename = "file.zip";
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
var client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
var url = "ftp://ftp.example.com/remote/path/" + filename;
using (var ftpStream = client.OpenRead(url))
{
ftpStream.CopyTo(Response.OutputStream);
}
(where Response is ASP.NET HttpResponse).
See also Upload and download a file to/from FTP server in C#/.NET.
I am trying to download a log file to my program without save it to my local machine, and get the last line of the log.
can anyone send me an example of it or look at the code and tell me what is wrong.
thanks
FileStream outputStream = new FileStream(uri, FileMode.Create);
request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.UseBinary = true;
request.Credentials = new NetworkCredential(userName, Password);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int readCount;
readCount = ftpStream.Read(b, 0, b.Length);
while (readCount > 0)
{
outputStream.Write(b, 0, readCount);
readCount = ftpStream.Read(b, 0, b.Length);
}
temp2 = System.Text.Encoding.UTF8.GetString(b);
temp1 = temp2.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
LastItem = temp1.Last();
ftpStream.Close();
outputStream.Close();
response.Close();
I'm newbie to FTP.I am trying to write to a file in FTP using StreamWriter.Once after writing to the file,i dont want to close the stream as i have some work which has to be done.Later after some 1 hour,if i try to write using the same streamWriter i get the above error.
Below is my code snippet
public void WriteToFTP()
{
bool isConnectionEstablished = false;
StreamWriter stream = null;
try
{
for (int i = 1; i < 5; i++)
{
string message = string.Format("File - {0}.", i.ToString());
if (!isConnectionEstablished)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri("My FTP path"));
request.Credentials = new NetworkCredential("asdf", "asdf#123");
request.Proxy = null;
request.UseBinary = true;
request.ConnectionGroupName = string.Empty;
request.UsePassive = true;
request.EnableSsl = false;
isConnectionEstablished = true;
stream = new StreamWriter(request.GetRequestStream()) { AutoFlush = true };
}
stream.WriteLine(message);//Here i am getting the error for the i = 2(after doing my work)
//Doing work which may take more than 1 hour.
}
}
catch (Exception exe)
{
//The Error "Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host" is being caught here.
}
finally
{
if (stream != null)
stream.Close();
}
}
you must set timout to infinity,-1 is the value for infinity, see this example:
FtpWebRequest reqFTP;
string fileName = #"c:\downloadDir\localFileName.txt";
FileInfo downloadFile = new FileInfo(fileName);
string uri = "ftp://ftp.myftpsite.com/ftpDir/remoteFileName.txt";
FileStream outputStream = new FileStream(fileName, FileMode.Append);
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.KeepAlive = false;
reqFTP.Timeout = -1;
reqFTP.UsePassive = true;
reqFTP.Credentials = new NetworkCredential("userName", "passWord");
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = ftpStream.Read(buffer, 0, bufferSize);
Console.WriteLine("Connected: Downloading File");
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
Console.WriteLine(readCount.ToString());
}
ftpStream.Close();
outputStream.Close();
response.Close();
Console.WriteLine("Downloading Complete");
I want to upload file from one server to another FTP server and following is my code to upload file but it is throwing an error as:
The remote server returned an error: (550) File unavailable (e.g., file not found, no access).
This my code:
string CompleteDPath = "ftp URL";
string UName = "UserName";
string PWD = "Password";
WebRequest reqObj = WebRequest.Create(CompleteDPath + FileName);
reqObj.Method = WebRequestMethods.Ftp.UploadFile;
reqObj.Credentials = new NetworkCredential(UName, PWD);
FileStream streamObj = System.IO.File.OpenRead(Server.MapPath(FileName));
byte[] buffer = new byte[streamObj.Length + 1];
streamObj.Read(buffer, 0, buffer.Length);
streamObj.Close();
streamObj = null;
reqObj.GetRequestStream().Write(buffer, 0, buffer.Length);
reqObj = null;
Can you please tell me where i am going wrong?
Please make sure your ftp path is set as shown below.
string CompleteDPath = "ftp://www.example.com/wwwroot/videos/";
string FileName = "sample.mp4";
WebRequest reqObj = WebRequest.Create(CompleteDPath + FileName);
The following script work great with me for uploading files and videos to another servier via ftp.
FtpWebRequest ftpClient = (FtpWebRequest)FtpWebRequest.Create(ftpurl + "" + username + "_" + filename);
ftpClient.Credentials = new System.Net.NetworkCredential(ftpusername, ftppassword);
ftpClient.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
ftpClient.UseBinary = true;
ftpClient.KeepAlive = true;
System.IO.FileInfo fi = new System.IO.FileInfo(fileurl);
ftpClient.ContentLength = fi.Length;
byte[] buffer = new byte[4097];
int bytes = 0;
int total_bytes = (int)fi.Length;
System.IO.FileStream fs = fi.OpenRead();
System.IO.Stream rs = ftpClient.GetRequestStream();
while (total_bytes > 0)
{
bytes = fs.Read(buffer, 0, buffer.Length);
rs.Write(buffer, 0, bytes);
total_bytes = total_bytes - bytes;
}
//fs.Flush();
fs.Close();
rs.Close();
FtpWebResponse uploadResponse = (FtpWebResponse)ftpClient.GetResponse();
value = uploadResponse.StatusDescription;
uploadResponse.Close();
Here are sample code to upload file on FTP Server
string filename = Server.MapPath("file1.txt");
string ftpServerIP = "ftp.demo.com/";
string ftpUserName = "dummy";
string ftpPassword = "dummy";
FileInfo objFile = new FileInfo(filename);
FtpWebRequest objFTPRequest;
// Create FtpWebRequest object
objFTPRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + objFile.Name));
// Set Credintials
objFTPRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
// By default KeepAlive is true, where the control connection is
// not closed after a command is executed.
objFTPRequest.KeepAlive = false;
// Set the data transfer type.
objFTPRequest.UseBinary = true;
// Set content length
objFTPRequest.ContentLength = objFile.Length;
// Set request method
objFTPRequest.Method = WebRequestMethods.Ftp.UploadFile;
// Set buffer size
int intBufferLength = 16 * 1024;
byte[] objBuffer = new byte[intBufferLength];
// Opens a file to read
FileStream objFileStream = objFile.OpenRead();
try
{
// Get Stream of the file
Stream objStream = objFTPRequest.GetRequestStream();
int len = 0;
while ((len = objFileStream.Read(objBuffer, 0, intBufferLength)) != 0)
{
// Write file Content
objStream.Write(objBuffer, 0, len);
}
objStream.Close();
objFileStream.Close();
}
catch (Exception ex)
{
throw ex;
}
You can also use the higher-level WebClient type to do FTP stuff with much cleaner code:
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
client.UploadFile("ftp://ftpserver.com/target.zip", "STOR", localFilePath);
}
In case you're still having issues here's what got me past all this.
I was getting the same error in-spite of the fact that I could perfectly see the file in the directory I was trying to upload - ie: I was overwriting a file.
My ftp url looked like:
// ftp://www.mywebsite.com/testingdir/myData.xml
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://www.mywebsite.com/testingdir/myData.xml"
So, my credentials use my tester username and PW;
request.Credentials = new NetworkCredential ("tester", "testerpw");
Well, my "tester" ftp account is set to "ftp://www.mywebsite.com/testingdir" but when I actually ftp [say from explorer] I just put in "ftp://www.mywebsite.com" and log in with my tester credentials and automatically get sent to "testingdir".
So, to make this work in C# I wound up using the url - ftp://www.mywebsite.com/myData.xml
Provided my tester accounts credentials and everything worked fine.
Please make sure your URL that you pass to WebRequest.Create has this format:
ftp://ftp.example.com/remote/path/file.zip
There are easier ways to upload a file using .NET framework.
Easiest way
The most trivial way to upload a file to an FTP server using .NET framework is using WebClient.UploadFile method:
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
client.UploadFile(
"ftp://ftp.example.com/remote/path/file.zip", #"C:\local\path\file.zip");
Advanced options
If you need a greater control, that WebClient does not offer (like TLS/SSL encryption, ascii/text transfer mode, transfer resuming, etc), use FtpWebRequest, like you do. But you can make the code way simpler and more efficient by using Stream.CopyTo:
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(#"C:\local\path\file.zip"))
using (Stream ftpStream = request.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
For even more options, including progress monitoring and uploading whole folder, see:
Upload file to FTP using C#
Here is the Solution !!!!!!
To Upload all the files from Local directory(ex:D:\Documents) to FTP url (ex: ftp:\{ip address}\{sub dir name})
public string UploadFile(string FileFromPath, string ToFTPURL, string SubDirectoryName, string FTPLoginID, string
FTPPassword)
{
try
{
string FtpUrl = string.Empty;
FtpUrl = ToFTPURL + "/" + SubDirectoryName; //Complete FTP Url path
string[] files = Directory.GetFiles(FileFromPath, "*.*"); //To get each file name from FileFromPath
foreach (string file in files)
{
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(FtpUrl + "/" + Path.GetFileName(file));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(FTPLoginID, FTPPassword);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
FileStream stream = File.OpenRead(FileFromPath + "\\" + Path.GetFileName(file));
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
}
return "Success";
}
catch(Exception ex)
{
return "ex";
}
}
public void UploadImageToftp()
{
string server = "ftp://111.61.28.128/Example/"; //server path
string name = #"E:\Apache\htdocs\visa\image.png"; //image path
string Imagename= Path.GetFileName(name);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(string.Format("{0}{1}", server, Imagename)));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("username", "password");
Stream ftpStream = request.GetRequestStream();
FileStream fs = File.OpenRead(name);
byte[] buffer = new byte[1024];
int byteRead = 0;
do
{
byteRead = fs.Read(buffer, 0, 1024);
ftpStream.Write(buffer, 0, byteRead);
}
while (byteRead != 0);
fs.Close();
ftpStream.Close();
MessageBox.Show("Image Upload successfully!!");
}
I am trying to use an FtpWebRequest to upload some files. This works for smallish files (say <2MB), but when I am trying to load a 16MB file, the files uploads successfully, but when I call request.GetRequestStream().Close, the code hangs (or timesout if the timeout is low enough).
I could just a) not close it and b)not bother to get the response from the server, but that doesn't seem right! See code below (using SSL or not, the same problem occurs.)
output.Close() is the line that hangs....
public static void SendFileViaFtp(string file, string url, bool useSsl, ICredentials credentials)
{
var request = (FtpWebRequest)WebRequest.Create(url + Path.GetFileName(file));
request.EnableSsl = useSsl;
request.UseBinary = true;
request.Credentials = credentials;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Timeout = 10000000;
request.ReadWriteTimeout = 10000000;
request.KeepAlive = true;
var input = File.Open(file, FileMode.Open);
var output = request.GetRequestStream();
var buffer = new byte[1024];
var lastBytesRead = -1;
var i = 0;
while (lastBytesRead != 0)
{
i++;
lastBytesRead = input.Read(buffer, 0, 1024);
Debug.WriteLine(lastBytesRead + " " + i);
if (lastBytesRead > 0)
{
output.Write(buffer, 0, lastBytesRead);
}else
{
Debug.WriteLine("Finished");
}
}
input.Close();
output.Close();
var response = (FtpWebResponse)request.GetResponse();
response.Close();
}
Thanks,
try
// after finished uploading
request.Abort(); // <=== MAGIC PART
// befor response.Close()
var response = (FtpWebResponse)request.GetResponse();
response.Close();
taken from here
try to close output before input.
make sure the last buffer isn't to large, or you could write a few empty bytes.
I don't know if it's necessary but i always set the request contentlength to the inputfile-length.
Here is an good example: http://dotnet-snippets.de/dns/ftp-file-upload-mit-buffer-SID886.aspx