C# FtpWebRequest progress bar tooltip update with uploaded amount - c#

I'm trying to write to my uploadProgress progress bar's toolTip the current uploaded amount, so when the user mouseovers the progress bar, the can see the tooltip changing showing the uploaded amount against the file size.
the code I have so far give me the "busy" icon when I mouse over, until the file has finished uploaded, and then it shows the downloaded amount and file size.
Could someone help me get this working ?
private void uploadFile()
{
try
{
richTextBox1.AppendText("\n\nStarting file upload");
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftpsite.com/public_html/test.htm");
request.Credentials = new NetworkCredential("username", "password");
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = true;
request.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(#"C:\path\testfile.UPLOAD"))
using (Stream ftpStream = request.GetRequestStream())
{
uploadProgress.Invoke(
(MethodInvoker)delegate {
uploadProgress.Maximum = (int)fileStream.Length; });
byte[] buffer = new byte[10240];
int read;
while ((read = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
ftpStream.Write(buffer, 0, read);
uploadProgress.Invoke(
(MethodInvoker)delegate {
uploadProgress.Value = (int)fileStream.Position;
toolTip1.SetToolTip(
uploadProgress, string.Format("{0} MB's / {1} MB's\n",
(uploadProgress.Value / 1024d / 1024d).ToString("0.00"),
(fileStream.Length / 1024d / 1024d).ToString("0.00")));
});
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Thanks

Your code works for me. Assuming you run the uploadFile on a background thread, like:
private void button1_Click(object sender, EventArgs e)
{
Task.Run(() => uploadFile());
}
See also How can we show progress bar for upload with FtpWebRequest
(though you know that link already)
You just update the tooltip too often, so it flickers.

Related

Download FTP using FtpWebRequest in Windows Form .Net

I have tried to download an FTP file using C# and have had various problems. What I want to achieve is to be able to show download progress in a progressBar. It is important that I use Windows Form and .Net.
I have tried two codes;
My first code works perfectly, that is, I can download the FTP file without problems.
CODE 1
FtpWebRequest dirFtp = ((FtpWebRequest)FtpWebRequest.Create(ficFTP));
dirFtp.KeepAlive = true;
dirFtp.UsePassive = UsePassive;
dirFtp.UseBinary = UseBinary;
// Los datos del usuario (credenciales)
NetworkCredential cr = new NetworkCredential(user, pass);
dirFtp.Credentials = cr;
FtpWebResponse response = (FtpWebResponse)dirFtp.GetResponse();
long size = (long)response.ContentLength;
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
using (FileStream writer = new FileStream(dirLocal, FileMode.Create))
{
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[2048];
readCount = responseStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
writer.Write(buffer, 0, readCount);
readCount = responseStream.Read(buffer, 0, bufferSize);
}
}
lblDescarga.Text = "¡Downloaded!";
reader.Close();
response.Close();
Problem with this code
My problem with this code is that I can't get the size of the FTP file to be able to use the progressBar, In theory this section of code would tell me the size of my file but it always returns -1:
long size = (long)response.ContentLength;
As this did not work as I wanted, I made a post and people recommended this solution FtpWebRequest FTP download with ProgressBar:
CODE 2
try
{
const string url = "ftp://185.222.111.11:21/patch/archive.zip";
NetworkCredential credentials = new NetworkCredential("user", "pass");
// Query size of the file to be downloaded
WebRequest sizeRequest = WebRequest.Create(url);
sizeRequest.Credentials = credentials;
sizeRequest.Method = WebRequestMethods.Ftp.GetFileSize;
int size = (int)sizeRequest.GetResponse().ContentLength;
progressBar1.Invoke(
(MethodInvoker)(() => progressBar1.Maximum = size));
// Download the file
WebRequest request = WebRequest.Create(url);
request.Credentials = credentials;
request.Method = WebRequestMethods.Ftp.DownloadFile;
using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(#"C:\tmp\archive.zip"))
{
byte[] buffer = new byte[10240];
int read;
while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, read);
int position = (int)fileStream.Position;
progressBar1.Invoke(
(MethodInvoker)(() => progressBar1.Value = position));
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
Problem with this code
The problem with this code is when it gets to this point:
int size = (int) sizeRequest.GetResponse (). ContentLength;
Remote server error: (550) File not available (eg file not found or not accessed).
The truth is that it is impossible to tell that you do not have permission if code 1 works well. However I have the normal permissions in FTP, could someone give me an idea please?

C# - Can't upload a file to FTP server while file is being written on by another program

I am basically trying to trace a specific file on my PC and whenever the file's content changes, it should be uploaded to my FTP server. The problem I'm facing is that it won't let me upload to my FTP server while the file is currently being written on by another process. I have tried everything, including opening in Administrator etc but this error (550 Permission denied) comes from the FTP server.
Here is my code:
public static void Trace()
{
string checksum = "";
while (true)
{
if (CheckMd5(Path) != checksum)
{
UploadFile1();
}
checksum = CheckMd5(Path);
Thread.Sleep(5000);
}
}
public static void UploadFile1()
{
var ftp1 = new myFTP();
if (!File.Exists(Path))
{
}
else
{
var currentTime = CurrentTime; // gets the current time
ftp1.UploadFile(Path, timeRn);
}
}
public void UploadFile(string filePath, string CurrentTime)
{
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://127.0.0.1/" + CurrentTime);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("user", "password");
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
request.EnableSsl = false;
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
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();
}
You should probably restructure those 2 processes so that the file-changing process fires an event after it's done changing the file, while the ftp-uploading process should stop forcing its way in by looping and comparing checksum values (just let it sit dormant and wait for the file-done signal). That approach will improve perf of your app as a bonus (aside from the accuracy that you need).
Aside from that, maybe try using FileSystemWatcher class. You can filter for modification events only.

Issue with video stream when header contains accept-ranges

I am trying to stream video from server with accept-ranges to allow users to change position on client-side video player (in my case jwplayer)
When accept-ranges code is included client (jwplayer or opened only in chrome directly from url) plays about 15s normally and after it is every chunk asked with new request, practically after 15s only goes through method only one time, connection is broken in or after Response.Flush() without any error (sometimes Flush() gets error code 0x800704CD or 0x800703E3 or 0x80070016 in about 10% of requests), after that is Response.IsClientConnected=false so method ends.
Client is asked for range for example 123456-empty, there is not specified end part of range.
I guess that this is not right behavior, maybe there is wrong headers on Response.. or is normal, that client video player is creating new request for every chunk? Actually it takes on my PC about 80% of CPU.
Problem is only while streaming video and when is created a lot of new requests in same time, in usual situations when file is downloaded there is no problem when is establishment of broken downloads for example.
When accept-ranges code missing, there is no problem in video streaming, all server->clients transfers are in while loop and only when user broke connection methods end.
(This solution is running under ASP.NET MVC4)
Currently used code :
public void Method()
{
string path = #"filePath.mp4";
FileInfo file = new FileInfo(path);
long fileLength = file.Length;
byte[] buffer = new byte[64 * 1024];
long dataToRead = fileLength;
long startbyte = 0;
long location = 0;
long readLength = 0;
Response.AddHeader("Accept-Ranges", "bytes");
Response.ContentType = "video/mp4";
if (!String.IsNullOrEmpty(Request.Headers["Range"]))
{
string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
location = long.Parse(range[1]);
if (location >= 0 && location <= fileLength)
{
Response.StatusCode = 206;
Response.AddHeader("content-range", String.Format(" bytes {0}-{1}/{2}", location, fileLength - 1, fileLength));
startbyte = location;
dataToRead = fileLength - startbyte;
Response.AppendHeader("content-length", dataToRead.ToString());
}
}
else
{
Response.StatusCode = 200;
Response.AddHeader("Content-Range", String.Format(" bytes {0}-{1}/{2}", 0, fileLength - 1, fileLength));
Response.AppendHeader("content-length", fileLength.ToString());
}
try
{
using (Stream stream = System.IO.File.OpenRead(path))
{
if (startbyte > 0)
{
stream.Seek(startbyte, SeekOrigin.Begin);
}
while (dataToRead > 0)
{
if (Response.IsClientConnected)
{
readLength = stream.Read(buffer, 0, buffer.Length);
Response.OutputStream.Write(buffer, 0, (int)readLength);
Response.Flush();
dataToRead = dataToRead - readLength;
}
else
{
dataToRead = -1;
}
}
}
}
catch (EndOfStreamException endStream)
{
Log.Error(endStream.Message, endStream);
}
catch (TimeoutException timeout)
{
Log.Error(timeout.Message, timeout);
}
catch (Exception e)
{
Log.Error(e.Message, e);
}
finally
{
Response.End();
}
}

uploading large file using ftpwebrequest upload wont complete

My software i designed uploads files using ftp to my sever I'm using the ftpwebrequest to do all uploading. When uploading a file 700mb it uploads about 500mbs then stops, it works fine when uploading smaller files the smaller files upload successfully but it just want work properly on large files. I have the uploading done in a background worker that reports the upload progress to a progress bar on the main client. When the background worker completes it executes the background worker completed function. The background worker completed function gets executed but the upload never completes and the progress bar is stuck at about 65 percent its like the client just stops uploading and executes the background worker completed function as though it completed uploading. What could be going wrong here the upload doesn't complete and the file dose not appear on the server here is the code that dose the uploading
void UploadFileInBackground_DoWork(object sender,DoWorkEventArgs e)
{
byte[] data;
int packetsize = 1024 * 8;
string Destination = UploadURI + cattext + "/" + ID + ".obj";
string source = DialogBrower.FileName;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(Destination);
request.Credentials = new NetworkCredential("user", "pass");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
using (FileStream fs = new FileStream(source, FileMode.Open, FileAccess.Read))
{
try
{
long filesize = fs.Length;
long sum = 0;
int count = 0;
data = new byte[packetsize];
Stream reqStream = request.GetRequestStream();
float totalpackits = filesize / packetsize;
float weightofpackit = 100 / totalpackits;
float percentage = 0;
while (sum < filesize)
{
List<string> statusparms = new List<string>();
count = fs.Read(data, 0, packetsize);
reqStream.Write(data, 0, count);
sum += count;
percentage += weightofpackit;
int percentagetotal = Convert.ToInt32(Math.Round(percentage));
statusparms.Add(sum.ToString());
statusparms.Add(filesize.ToString());
UploadFileInBackground.ReportProgress(percentagetotal, statusparms);
}
reqStream.Close();
uploadedname = uploadingname;
}
finally
{
fs.Dispose();
data = null;
}
}
}
Please try this instead:
request.UseBinary = false;
let's try this
request.KeepAlive = false;
to
request.KeepAlive = true;

c# Uploading files to ftp server

I have a problem with uploading files to ftp server. I have a few buttons. Every button uploads different files to the ftp. The first time when a button is clicked the file is uploaded successfully, but the second and later tries fail. It gives me "The operation has timed out". When I close the site and then open it again I can upload again only one file. I am sure that I can override files on the ftp. Here's the code:
protected void btn_export_OnClick(object sender, EventArgs e)
{
Stream stream = new MemoryStream();
stream.Position = 0;
// fill the stream
bool res = this.UploadFile(stream, "test.csv", "dir");
stream.Close();
}
private bool UploadFile(Stream stream, string filename, string ftp_dir)
{
stream.Seek(0, SeekOrigin.Begin);
string uri = String.Format("ftp://{0}/{1}/{2}", "host", ftp_dir, filename);
try
{
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential("user", "pass");
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.KeepAlive = false;
reqFTP.UseBinary = true;
reqFTP.UsePassive = true;
reqFTP.ContentLength = stream.Length;
reqFTP.EnableSsl = true; // it's FTPES type of ftp
int buffLen = 2048;
byte[] buff = new byte[buffLen];
int contentLen;
try
{
Stream ftpStream = reqFTP.GetRequestStream();
contentLen = stream.Read(buff, 0, buffLen);
while (contentLen != 0)
{
ftpStream.Write(buff, 0, contentLen);
contentLen = stream.Read(buff, 0, buffLen);
}
ftpStream.Flush();
ftpStream.Close();
}
catch (Exception exc)
{
this.lbl_error.Text = "Error:<br />" + exc.Message;
this.lbl_error.Visible = true;
return false;
}
}
catch (Exception exc)
{
this.lbl_error.Text = "Error:<br />" + exc.Message;
this.lbl_error.Visible = true;
return false;
}
return true;
}
Does anyone have idea what may cause this strange behaviour? I think I'm closing all streams accurately. Could this be related with the ftp server settings? The admin said that the ftp handshake never happened second time.
start with wrapping your Stream creation in a using clause.
using(Stream stream = new MemoryStream())
{
stream.Position = 0;
// fill the stream
bool res = this.UploadFile(stream, "test.csv", "dir");
}
This will make sure that the stream is closed and that any unmanaged resources are disposed, whether an error occurs or not
I used your code, had the same problem, and fixed it.
After you close the stream, you have to read reqFTP response by calling GetResponse() then close the response. Here is the code that fixes the problem:
// Original code
ftpStream.Flush();
ftpStream.Close();
// Here is the missing part that you have to add to fix the problem
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
this.lbl_error.Text = "Response:<br />" + response.StatusDescription;
response.Close();
reqFTP = null;
this.lbl_error.Visible = true;
You don't have to display the response, you can just get it and close it, I am displaying it just for reference.

Categories

Resources