How can I upload a PDF file to host via C# so that it is available for download via an adroid app? This is what I have tried, but it does not work. What am I doing wrong?
static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
string fileName = ((FTPsetting)e.Argument).Filename;
string fullName = ((FTPsetting)e.Argument).FullName;
string username = ((FTPsetting)e.Argument).Username;
string password = ((FTPsetting)e.Argument).Password;
string server = ((FTPsetting)e.Argument).Server;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(string.Format("{0}/{1}", server, fileName)));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(username, password);
Stream ftpstream = request.GetRequestStream();
FileStream fs = File.OpenRead(fullName);
byte[] buffer = new byte[1024];
double total = (double)fs.Length;
int byteread = 0;
double read = 0;
do
{
if (!backgroundWorker.CancellationPending)
{
byteread = fs.Read(buffer, 0, 1024);
ftpstream.Write(buffer, 0, byteread);
read += (double)byteread;
double percontage = read / total * 100;
backgroundWorker.ReportProgress((int)percontage);
}
}
while (byteread != 0);
fs.Close();
ftpstream.Close();
}
static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine("Completed" + e.ProgressPercentage + "%");
}
Related
I've tried downloading file from FTP server in chunks using the FtpWebRequest and merging the chunks to original file. The process works fine for 4GB or lower files but when trying the same process for 8 or 9GB files I'm getting an error
Here is the error I'm getting
Here is the sample code I've worked out
private static long limitSize = Convert.ToInt64(ConfigurationManager.AppSettings["LimitSize"]);
public static void DownloadFromFTP()
{
var guid = Guid.NewGuid().ToString();
var path = $"{System.Environment.CurrentDirectory}/UploadedFiles/{guid}";
try
{
string strFilePath = ConfigurationManager.AppSettings["FilePath"];
NetworkCredential credentials = new NetworkCredential(ConfigurationManager.AppSettings["UserName"], ConfigurationManager.AppSettings["Password"]);
Console.WriteLine("Starting...");
string name = ConfigurationManager.AppSettings["FileName"];
var strFolderPath = ConfigurationManager.AppSettings["Key"] + name;
FtpWebRequest sizeRequest = (FtpWebRequest)WebRequest.Create(strFilePath);
sizeRequest.KeepAlive = false;
sizeRequest.Credentials = credentials;
sizeRequest.Method = WebRequestMethods.Ftp.GetFileSize;
long size = sizeRequest.GetResponse().ContentLength;
Console.WriteLine($"File has {size} bytes");
double filesizecheck = Convert.ToDouble(size) / Convert.ToDouble(limitSize);
int chunks = Convert.ToInt32(Math.Ceiling(filesizecheck));
long chunkLength = size / chunks;
List<Task> tasks = new List<Task>();
if (!System.IO.Directory.Exists(path))
{
System.IO.Directory.CreateDirectory(path);
}
var filepath = $"{path}/{name}";
for (int chunk = 0; chunk < chunks; chunk++)
{
int i = chunk;
tasks.Add(Task.Run(() =>
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(strFilePath);
request.Credentials = credentials;
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = false;
request.ContentOffset = chunkLength * i;
long toread =
(i < chunks - 1) ? chunkLength : size - request.ContentOffset;
Console.WriteLine(
$"Downloading chunk {i + 1}/{chunks} with {toread} bytes ...");
using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(filepath + "." + i))
{
var bufferSize = Convert.ToInt32(ConfigurationManager.AppSettings["BufferSize"]);
byte[] buffer = new byte[bufferSize];
int read;
while (((read = (int)Math.Min(buffer.Length, toread)) > 0) &&
((read = ftpStream.Read(buffer, 0, read)) > 0))
{
fileStream.Write(buffer, 0, read);
toread -= read;
}
}
Console.WriteLine($"Downloaded chunk {i + 1}/{chunks}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex}");
Console.ReadKey();
}
}));
}
Console.WriteLine("Started all chunks downloads, waiting for them to complete...");
Task.WaitAll(tasks.ToArray());
CombineMultipleFilesIntoSingleFile(path, filepath);
var result = UploadToS3(filepath, strFolderPath, size, path).Result;
Console.WriteLine("Done");
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine("Exception " + ex.Message);
DeleteFiles(path);
Console.ReadKey();
}
Console.ReadKey();
Console.ReadKey();
}
Here is the method to merge the files
private static void CombineMultipleFilesIntoSingleFile(string inputDirectoryPath, string outputFilePath)
{
string[] inputFilePaths = Directory.GetFiles(inputDirectoryPath);
Console.WriteLine("Number of files: {0}.", inputFilePaths.Length);
using (var outputStream = File.Create(outputFilePath))
{
foreach (var inputFilePath in inputFilePaths)
{
using (var inputStream = File.OpenRead(inputFilePath))
{
// Buffer size can be passed as the second argument.
inputStream.CopyTo(outputStream);
}
Console.WriteLine("The file {0} has been processed.", inputFilePath);
}
}
}
App Config settings
<add key="LimitSize" value="10000000"/>
<add key="BufferSize" value="10240"/>
This is the method:
Getting the Length of the files give 0 already.
public void DownloadFtpContent(object sender ,string file, string filesdirectories,string fn)
{
try
{
BackgroundWorker bw = sender as BackgroundWorker;
string filenameonly = Path.GetFileName(file);
string ftpdirectories = Path.Combine(ftpcontentdir, filesdirectories);
string fileurl = "ftp://" + file;
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(fileurl);
reqFTP.Credentials = new NetworkCredential(UserName, Password);
reqFTP.UseBinary = true;
reqFTP.UsePassive = true;
reqFTP.KeepAlive = true;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.Proxy = null;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream responseStream = response.GetResponseStream();
if (!Directory.Exists(ftpdirectories))
{
Directory.CreateDirectory(ftpdirectories);
}
FileStream writeStream = new FileStream(ftpdirectories + "\\" + filenameonly, FileMode.Create);
string fnn = ftpdirectories + "\\" + filenameonly;
int Length = 2048;
Byte[] buffer = new Byte[Length];
int bytesRead = responseStream.Read(buffer, 0, Length);
long FileSize = new FileInfo(fnn).Length;
string FileSizeDescription = GetFileSize(FileSize);
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = responseStream.Read(buffer, 0, Length);
string SummaryText = String.Format("Transferred {0} / {1}", GetFileSize(bytesRead), FileSizeDescription);
bw.ReportProgress((int)(((decimal)bytesRead / (decimal)FileSize) * 100), SummaryText);
}
writeStream.Close();
response.Close();
}
catch (WebException wEx)
{
//MessageBox.Show(wEx.Message, "Download Error");
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message, "Download Error");
}
}
}
Already on this line the result is 0:
long FileSize = new FileInfo(fnn).Length;
In fnn i have: c:\myftpdownloads\root\Images\CB 967x330.jpg
Why the result of the Length is 0 ?
And the file is not 0kb size.
EDIT
This is how i'm calling the download method from backgroundworker dowork event:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < numberOfFiles.Count; i++)
{
int fn = numberOfFiles[i].IndexOf(txtHost.Text, 0);
string fn1 = numberOfFiles[i].Substring(txtHost.Text.Length + 1, numberOfFiles[i].Length - (txtHost.Text.Length + 1));
string dirs = Path.GetDirectoryName(fn1);
string filename = Path.GetFileName(fn1);
ftpProgress1.DownloadFtpContent(sender,numberOfFiles[i], dirs, filename);
}
}
In fnn i have: c:\myftpdownloads\root\Images\CB 967x330.jpg Why the result of the Length is 0 ?
It doesn't really matter why the result of the length is 0. It does matter that you divide that number by 0 without any protection.
Just check before you divide:
if( FileSize != 0 ){...}
I want to create a TcpClient which automatically gets multiple files from server by their name.
I want to get some ideas how I can build such application.
My idea is:
Make a for loop which contains SwitchCase, where I specify my files names. I really don't know if this will work well.
To go out of for loop I can compare the index operator to numbers of files. If they are equal then I go out of for loop.
Example of my idea:
for (int i = 1; i <= 4; i++)
{
switch (----)
{
case 'file1':
code...
break;
case 'file2':
code...
case 'file3':
code...
break;
case 'file4':
code...
break;
default:
code...
break;
}
}
To download a file using ftp you could use the FtpWebRequest and for http use the HttpWebRequest.
Below is a simple example of how to request a file using http (the method is similar for ftp):
public void Download(string url, string localPath)
{
HttpWebRequest request = HttpWebRequest.Create(url);
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream stream = response.GetResponseStream();
FileStream fs = new FileStream(localPath, FileMode.Create);
int count;
byte[] buffer = new byte[8096];
while ((count = stream.Read(buffer, 0, 8096)) > 0)
fs.Write(buffer, 0, count);
fs.Dispose();
response.Close();
}
Instead of using a switch inside a for loop you should iterate an array:
string[] files = new string[]{ url1, url2, ...};
for(int i = 0; i < files.Length; i++)
{
Download(files[i], "file" + i);
}
I solved it like so:
MY app. gets 2 files from server and move files and rename them.
test = mytest
test111 = test2
static string myfile1 = #"C:\inbox\mytest.txt";
static string myfile2 = #"C:\inbox\test2.txt";
//files from server
static string myServerfile = #"C:\Users\me\Documents\file_client\bin\Debug\test.csv";
static string myServerfile1 = #"C:\Users\RH-T3\Documents\file_client\bin\Debug\test111.txt";
public static void Main(string[] args)
{
try
{
for (int i = 0; i < 2; i++)
{
if (i == 0)
{
Console.WriteLine("Downloading test.csv");
string fileName = "test.csv";
Console.WriteLine("Client starts...");
//args[0] = Console.ReadLine();
file_client client = new file_client(args);
Console.WriteLine("efter file_client...");
NetworkStream serverStream = client.clientSocket.GetStream();
LIB.writeTextTCP(serverStream, fileName);
long rest = long.Parse(LIB.readTextTCP(serverStream));
byte[] inStream = new byte[rest];
while (rest != 0)
{
rest = rest - serverStream.Read(inStream, 0, inStream.Length);
Console.WriteLine("REST: " + rest);
}
FileStream fs = new FileStream(fileName, FileMode.Create);
fs.Write(inStream, 0, inStream.Length);
{
fs.Close();
serverStream.Close();
}
if (File.Exists(myfile1))
{
File.Delete(myfile1);
}
File.Move(myServerfile, myfile1);
Console.WriteLine("Moved");
System.Threading.Thread.Sleep(500);
}
else
{
Console.WriteLine("Downloading .txt file");
string fileName = "test111.txt";
Console.WriteLine("Client starts...");
//args[0] = Console.ReadLine();
file_client client = new file_client(args);
Console.WriteLine("efter file_client...");
NetworkStream serverStream = client.clientSocket.GetStream();
LIB.writeTextTCP(serverStream, fileName);
long rest = long.Parse(LIB.readTextTCP(serverStream));
byte[] inStream = new byte[rest];
while (rest != 0)
{
rest = rest - serverStream.Read(inStream, 0, inStream.Length);
Console.WriteLine("REST: " + rest);
}
FileStream fs = new FileStream(fileName, FileMode.Create);
fs.Write(inStream, 0, inStream.Length);
{
fs.Close();
serverStream.Close();
}
if (File.Exists(myfile2))
{
File.Delete(myfile2);
}
File.Move(myServerfile1, myfile2);
Console.WriteLine("Moved");
System.Threading.Thread.Sleep(500);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.WriteLine("Cannot be DONE!");
}
hi people I'm trying to put a download progress bar to my ftp download program it kinda works but progress bar is not filling with the download or after download but i get the download completed message the code is below ;
public void yap(object o)
{
(o as Label).Text = "DOWNLOADING";
}
private void button1_Click(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false;
ParameterizedThreadStart p = new ParameterizedThreadStart(yap);
Thread t = new Thread(p);
t.Start(label2);
BackgroundWorker _backgroundWorker = new BackgroundWorker();
_backgroundWorker.DoWork += _backgroundWorker_DoWork;
_backgroundWorker.WorkerReportsProgress = true;
_backgroundWorker.ProgressChanged +=
new ProgressChangedEventHandler(_backgroundWorker_ProgressChanged);
_backgroundWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);
_backgroundWorker.RunWorkerAsync();
}
void _backgroundWorker_RunWorkerCompleted
(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Download Completed");
}
void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void Form1_Load(object sender, EventArgs e)
{
AutoSizeMode = AutoSizeMode.GrowAndShrink;
progressBar1.Maximum = 100;
}
void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
Dispatcher.CurrentDispatcher.Invoke
(System.Windows.Threading.DispatcherPriority.Background,new Action(delegate()
{
string yol = Environment.CurrentDirectory;
FtpWebRequest FTP;
try
{
FileStream SR = new FileStream(yol + "\\list.gz", FileMode.Create);
FTP = (FtpWebRequest)FtpWebRequest.Create(new Uri
("ftp://" + textBox1.Text + "/" + "/usr/valapp/etc/list.gz"));
FTP.Credentials = new NetworkCredential("username", "password");
FTP.Method = WebRequestMethods.Ftp.DownloadFile;
FTP.UseBinary = true;
FtpWebResponse response = (FtpWebResponse)FTP.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);
while (readCount > 0)
{
SR.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
SR.Close();
response.Close();
MessageBox.Show("File Downloaded!");
for (int i = 0; i <= 100; i++)
{
backgroundWorker1.ReportProgress(i);
System.Threading.Thread.Sleep(20);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}));
}
}
}
Code might be look complex but its totally works as i told only progress bar is not filling thank you.
int cnt=0;
double totalentry=response.ContentLength/bufferSize;
while (readCount > 0)
{
SR.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
if(_backgroundWorker.WorkerReportsProgress)
{
_backgroundWorker.ReportProgress(cnt++*100/(int)totalentry);
}
}
You may just edit this part of the code.
I am developing an application which downloads videos from a given URL. The problem is that I do not receive the entire file content, then cannot play the file. For example, trying to download a video of size ~2.23 MB, gives me only ~2.11 MB. When I use the URL in a browser it shows me a dialog to save the video and the file is downloaded successfully.
I have tried using WebClient class and it works, but I want to download the file in chunks in order to be able to report the status(percentage completed). Here is the code I use:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
int bufferSize = 1024 * 300;
string filePath = saveFileDialog.FileName;
if (File.Exists(filePath))
File.Delete(filePath);
int totalBytes = 0;
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(DownloadUrl);
long contentLength = webRequest.GetResponse().ContentLength;
using (Stream webStream = webRequest.GetResponse().GetResponseStream())
using (StreamReader reader = new StreamReader(webStream))
using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath)))
{
do
{
char[] buffer = new char[bufferSize];
bytesRead = reader.ReadBlock(buffer, 0, bufferSize); // also tried with Read(buffer, 0, bufferSize);
totalBytes += bytesRead;
Console.WriteLine("Bytes read: " + bytesRead + " Total Bytes: " + totalBytes + " Content length: " + contentLength);
if (bytesRead > 0)
fileWriter.Write(buffer, 0, bytesRead);
} while (!reader.EndOfStream);
}
}
I have also tried to read until bytesRead = 0, but it's the same result.
Is there something that I am missing?
I would recommend that you use DownloadFileAsync instead. This provides you with two events that makes it much easier to track the progress of your download.
DownloadProgressChangedEventHandler
DownloadFileCompleted
A very simple implementation would look something like this.
WebClient client = new WebClient();
client.DownloadProgressChanged +=
new DownloadProgressChangedEventHandler(DownloadProgressCallback);
client.DownloadFileAsync(DownloadUrl, filePath);
Then have a function that updates your progress bar.
private void DownloadProgressCallback(object sender,
DownloadProgressChangedEventArgs e)
{
myProgressBar.Value = e.ProgressPercentage;
}
You also have access to data like e.BytesReceived and e.TotalBytesToReceive.
Edit:
The main change I had to do was to change your buffer from char[] to byte[], and then use a Stream instead of a StreamReader.
We also check the end of file by checking to see if there are any bytes to write to our hard-drive. If there are none left to write, we know that we are done.
private static void download()
{
int bufferSize = 1024 * 300;
string filePath = "Test.exe";
if (File.Exists(filePath))
File.Delete(filePath);
int totalBytes = 0;
HttpWebRequest webRequest =
(HttpWebRequest)
HttpWebRequest.Create(
#"http://www.rarlab.com/rar/wrar420.exe");
long contentLength = webRequest.GetResponse().ContentLength;
Console.WriteLine(totalBytes);
using (WebResponse webResponse = webRequest.GetResponse())
using (Stream reader = webResponse.GetResponseStream())
using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath)))
{
int bytesRead = 0;
byte[] buffer = new byte[bufferSize];
do
{
bytesRead = reader.Read(buffer, 0, buffer.Length);
totalBytes += bytesRead;
fileWriter.Write(buffer, 0, bytesRead);
Console.WriteLine("BytesRead: " + bytesRead + " -- TotalBytes: " + totalBytes);
} while (bytesRead > 0);
}
}
Try
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
int bufferSize = 1024 * 300;
string filePath = saveFileDialog.FileName;
if (File.Exists(filePath))
File.Delete(filePath);
int totalBytes = 0;
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(DownloadUrl);
long contentLength = webRequest.GetResponse().ContentLength;
using (Stream webStream = webRequest.GetResponse().GetResponseStream())
using (StreamReader reader = new StreamReader(webStream))
using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath)))
{
do
{
char[] buffer = new char[bufferSize];
bytesRead = reader.ReadBlock(buffer, 0, bufferSize); // also tried with Read(buffer, 0, bufferSize);
totalBytes += bytesRead;
Console.WriteLine("Bytes read: " + bytesRead + " Total Bytes: " + totalBytes + " Content length: " + contentLength);
if (bytesRead > 0)
fileWriter.Write(buffer, 0, bytesRead);
} while (!reader.EndOfStream);
fileWriter.flush();
}
}
Hi, that was my bad, I just added the fileWriter.flush(); outside the loop