我的意思是,如果我为30个文件的上传提供一个列表,它将打开30个上传插槽将实时上传所有文件,因此我将看到30个progressBars,它将上传所有文件并行。
在form1设计器中,我已经有一个progressBar。
这是ftp上传的类代码:
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
namespace FTP_ProgressBar
{
/// <summary>
/// The FtpProgress class is derived from background worker, so it has the built-in functions of
/// run, report progress, and completed.
/// It only does upload, as a demonstration of how to transfer a file by FTP and report the progress.
/// </summary>
public partial class FtpProgress : BackgroundWorker
{
public FtpProgress()
{
InitializeComponent();
}
public FtpProgress(IContainer container)
{
container.Add(this);
InitializeComponent();
}
private void FtpProgress_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
FtpSettings f = e.Argument as FtpSettings;
// set up the host string to request. this includes the target folder and the target file name (based on the source filename)
string UploadPath = String.Format("{0}/{1}{2}", f.Host, f.TargetFolder == "" ? "" : f.TargetFolder + "/", Path.GetFileName(f.SourceFile));
if(!UploadPath.ToLower().StartsWith("ftp://"))
UploadPath = "ftp://" + UploadPath;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(UploadPath);
request.UseBinary = true;
request.UsePassive = f.Passive;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(f.Username, f.Password);
// Copy the contents of the file to the request stream.
long FileSize = new FileInfo(f.SourceFile).Length;
string FileSizeDescription = GetFileSize(FileSize); // e.g. "2.4 Gb" instead of 240000000000000 bytes etc...
int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
long SentBytes = 0;
byte[] Buffer = new byte[ChunkSize]; // this buffer stores each chunk, for sending to the web service via MTOM
using(Stream requestStream = request.GetRequestStream())
{
using(FileStream fs = File.Open(f.SourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
int BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the first chunk in the buffer
// send the chunks to the web service one by one, until FileStream.Read() returns 0, meaning the entire file has been read.
while(BytesRead > 0)
{
try
{
if(bw.CancellationPending)
return;
// send this chunk to the server. it is sent as a byte[] parameter, but the client and server have been configured to encode byte[] using MTOM.
requestStream.Write(Buffer, 0, BytesRead);
// sentBytes is only updated AFTER a successful send of the bytes. so it would be possible to build in 'retry' code, to resume the upload from the current SentBytes position if AppendChunk fails.
SentBytes += BytesRead;
// update the user interface
string SummaryText = String.Format("Transferred {0} / {1}", GetFileSize(SentBytes), FileSizeDescription);
bw.ReportProgress((int)(((decimal)SentBytes / (decimal)FileSize) * 100), SummaryText);
}
catch(Exception ex)
{
Debug.WriteLine("Exception: " + ex.ToString());
if(NumRetries++ < MaxRetries)
{
// rewind the filestream and keep trying
fs.Position -= BytesRead;
}
else
{
throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
}
}
BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the next chunk (if it exists) into the buffer. the while loop will terminate if there is nothing left to read
}
}
}
using(FtpWebResponse response = (FtpWebResponse)request.GetResponse())
System.Diagnostics.Debug.WriteLine(String.Format("Upload File Complete, status {0}", response.StatusDescription));
}
/// <summary>
/// Returns a description of a number of bytes, in appropriate units.
/// e.g.
/// passing in 1024 will return a string "1 Kb"
/// passing in 1230000 will return "1.23 Mb"
/// Megabytes and Gigabytes are formatted to 2 decimal places.
/// Kilobytes are rounded to whole numbers.
/// If the rounding results in 0 Kb, "1 Kb" is returned, because Windows behaves like this also.
/// </summary>
public static string GetFileSize(long numBytes)
{
string fileSize = "";
if(numBytes > 1073741824)
fileSize = String.Format("{0:0.00} Gb", (double)numBytes / 1073741824);
else if(numBytes > 1048576)
fileSize = String.Format("{0:0.00} Mb", (double)numBytes / 1048576);
else
fileSize = String.Format("{0:0} Kb", (double)numBytes / 1024);
if(fileSize == "0 Kb")
fileSize = "1 Kb"; // min.
return fileSize;
}
}
public class FtpSettings
{
public string Host, Username, Password, TargetFolder, SourceFile;
public bool Passive;
public int Port = 21;
}
}
在form1:上传按钮点击事件:
private void btnUpload_Click(object sender, EventArgs e)
{
// the upload button is also used as a cancel button, depending on the state of the FtpProgress thread
if(this.ftpProgress1.IsBusy)
{
this.ftpProgress1.CancelAsync();
this.btnUpload.Text = "Upload";
}
else
{
// create a new FtpSettings class to store all the paramaters for the FtpProgress thread
FtpSettings f = new FtpSettings();
f.Host = this.txtHost.Text;
f.Username = this.txtUsername.Text;
f.Password = this.txtPassword.Text;
f.TargetFolder = this.txtDir.Text;
f.SourceFile = this.txtUploadFile.Text;
f.Passive = this.chkPassive.Checked;
try
{
f.Port = Int32.Parse(this.txtPort.Text);
}
catch { }
this.toolStripProgressBar1.Visible = true;
this.ftpProgress1.RunWorkerAsync(f);
this.btnUpload.Text = "Cancel";
}
}
Backgorundworker progresschanged:
private void ftpProgress1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.toolStripStatusLabel1.Text = e.UserState.ToString(); // the message will be something like: 45 Kb / 102.12 Mb
this.toolStripProgressBar1.Value = Math.Min(this.toolStripProgressBar1.Maximum, e.ProgressPercentage);
}
完成的活动:
private void ftpProgress1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error != null)
MessageBox.Show(e.Error.ToString(), "FTP error");
else if(e.Cancelled)
this.toolStripStatusLabel1.Text = "Upload Cancelled";
else
this.toolStripStatusLabel1.Text = "Upload Complete";
this.btnUpload.Text = "Upload";
this.toolStripProgressBar1.Visible = false;
}
在form1设计器中有一些文本框,我输入密码用户名ftp地址和要上传的文件。
这是用于上传的文件浏览器:
private void btnBrowse_Click(object sender, EventArgs e)
{
if(this.openFileDialog1.ShowDialog() != DialogResult.Cancel)
this.txtUploadFile.Text = this.openFileDialog1.FileName;
}
现在改为我希望能够选择多个文件的单个文件,如果我选择了多个文件,那么它将实时上传所选文件的数量。 如果我选择了2个文件,它将创建另一个新的progressBar,并将在文件上传的两个progressBars上显示。
如果我将选择34个文件,它将创建34个progressBars,并在其上显示上传进度。
答案 0 :(得分:0)
一次浏览多个文件时,操作仅发生一次。即;所有选定的文件都将到达您指定的位置(服务器)。所以,这就是你只能看到一个进度条的原因。
如果您需要多个进度条,则应尝试放置多个按钮,以便通过每个按钮选择每个文件。