Incomplete/Corrupted downloaded files - c#

I have made this little tool wich goes through a list of image links and download them to the hard drive, however, some of the pictures are incomplete (Check this picture) and they don't even raise an exception. The code below shows the download method I'm using in my tool.
private void Download(string url)
{
try
{
HttpWebRequest Request = WebRequest.Create(url) as HttpWebRequest;
Request.Method = WebRequestMethods.Http.Get;
Request.Timeout = 60 * 1000;
FileInfo ImageFile = new FileInfo(Path.Combine(BaseDirectory, Path.GetFileName(url)));
if (!ImageFile.Exists)
{
using (HttpWebResponse Response = Request.GetResponse() as HttpWebResponse)
{
if (Response.StatusCode.Equals(HttpStatusCode.OK))
{
using (FileStream FStream = new FileStream(ImageFile.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096))
Response.GetResponseStream().CopyTo(FStream, 4096);
}
}
}
}
catch (Exception e)
{
Console.WriteLine("Error Downloading: {0}\r\nMessage: {1}", url, e.Message);
}
}
I can't figure out whether the problem is on the server side or there is something wrong with my code, so what do you think?

Have you tried calling Flush() after you've read the data? It looks like the last part of the stream isn't being written out.

Related

How to upload images and video to a web server?

I have the following code. The upload was successfully but the images and videos are broken. I think the problem is because the encoding set to UTF8. How do I upload images and videos to the web server in C#?
private static void Upload(string ftpFilePath, string file)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpFilePath);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(Properties.Settings.Default.FtpUser, Properties.Settings.Default.FtpPass);
using (Stream fileStream = File.OpenRead(file))
using (Stream ftpStream = request.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
FtpWebResponse response = null;
try
{
response = (FtpWebResponse)request.GetResponse();
// Output message on screen
Log.Write($"{request.Method} {ftpFilePath}", Log.Status.UPLOADED);
}
catch (Exception ex)
{
// Output message on screen
Log.Write($"FTP UPLOAD: {response.StatusCode} - {ex.Message}", Log.Status.ERROR);
}
}

FTP downloading a file from a server

I am trying to download a file from a MOXA UC8410 over FTP. My code is not working. Here is my code:
void download2()
{
Uri serverUri = new Uri("ftp://169.254.1.1/CFDisk/PCPACM/pcpacm.ini");
// The serverUri parameter should start with the ftp:// scheme.
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
}
// Get the object used to communicate with the server.
WebClient request = new WebClient();
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential("admin", "admin");
try
{
byte[] newFileData = request.DownloadData(serverUri.ToString());
string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
//Console.WriteLine(fileString);
}
catch (WebException e)
{
// Console.WriteLine(e.ToString());
MessageBox.Show(e.Response + e.Message);
}
}
I have also tried this :
void download()
{
try
{
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri("ftp://169.254.1.1:21/CFDisk/PCPACM/pcpacm.ini"));
// using admin as the username and admin as the passward.
request.Credentials = new NetworkCredential("admin", "admin");
//request.KeepAlive = false;
request.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
processingfile(reader);
responseStream.Close();
reader.Close();
}
catch (Exception e2)
{
MessageBox.Show("Not connected" , e2.Message);
}
}
The code get to
Stream responseStream = response.GetResponseStream();
and it just stops, it never goes to the next line.
output says:
The thread 0x175c has exited with code 259 (0x103).
The thread 0x212c has exited with code 259 (0x103).
which does not help.
I can ftp to the MOXA UC8410 using the command prompt and I can download the file using FileZilla but not using my code. There is no firewall on the Moxa UC8410, so something most be wrong with my code.
UpDate:
UpDATE It is working !!!
but only if I go to local Area Connection Properties and change Internet Protocol Version 4(tcp/IPv4) to
use the following IP address:
IP address: 169.254.1.5
Subnet mask: 225.225.0.0
does anyone know why? and is there a way I can fix it where I do not have to do that ?
Why do I have to put them on the same sub domain ?
Since I cannot comment yet, I'll put my questions here:
1) When you log in using FileZilla, are you starting in the directory where CFDisk lies?
2) Are you using plain-text FTP? When using FTP over TLS, the approach is slightly different.
3) Does it throw an Exception? If so, please also give us more details about that.
Also, WebResponse, Stream and StreamReader are disposable.
I created (and tested on one of my remote servers) this little Windows Form application. It seems to work fine here. Give it a look.
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
namespace FTPTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string localPath = #"C:\Temp\navigazione-privata.pdf";
string ftpIPAddress = "xxx.xxx.xxx.xxx";
string remoteFilepath = "/userdownloads/navigazione-privata.pdf";
string ftpPath = "ftp://" + ftpIPAddress + remoteFilepath;
using (WebClient request = new WebClient())
{
request.Credentials = new NetworkCredential("username", "password");
byte[] fileData = request.DownloadData(ftpPath);
using (FileStream file = File.Create(localPath))
{
file.Write(fileData, 0, fileData.Length);
file.Close();
}
MessageBox.Show("Requested file downloaded");
}
}
}
}

A first chance exception of type "System.ArgumentException" occured in mscorlib.dll

try
{
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
}
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
Console.WriteLine(read1.ReadToEnd());
Console.WriteLine("Directory is compleate,status(0)",
res.StatusDescription);
read1.Close();
rs.Close();
}
catch (Exception e1)
{
Console.WriteLine(e1.Message);
}
I am trying to access ftp server via C#.
However, the code errors with an exception:
A first chance exception of type "System.ArgumentException" occured in mscorlib.dll. Stream was not readable.
Any help will be appreciated.
Put all IDisposable resources within using(...) {...}. That technics prevents
resource leaking/closed resources invoking:
try {
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
// Response: we're going to work wuth respose within "using" block only
using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
Console.WriteLine(resp.WelcomeMessage);
// Reader: once again reader's opened once and called within using only
using (StreamReader reader = new StreamReader(resp.GetResponseStream())) {
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("Directory is complete, status(0)", resp.StatusDescription);
}
}
catch (Exception ex) { // <- Bad idea to catch all possible exceptions without "throw;"
Console.WriteLine(ex.Message);
}
TLDR; The state of the FtpWebResponse object is disposed, therefore you cannot read the response stream. The stream is closed.
Disassembly of FtpWebResponse:
public override void Close()
{
if (Logging.On)
{
Logging.Enter(Logging.Web, this, "Close", "");
}
if (this.HttpProxyMode)
{
this.m_HttpWebResponse.Close();
}
else
{
Stream responseStream = this.m_ResponseStream;
if (responseStream != null)
{
responseStream.Close();
}
}
if (Logging.On)
{
Logging.Exit(Logging.Web, this, "Close", "");
}
}
The reason you get the exception, is that you are reading the response:
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
}
and on the next line, you try to read the response again, into another variable: res
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
In that section, you also do a call to the res.GetResponseStream() twice, but that does not matter in terms of the error occuring. The error will occur even if you change it to:
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A
Or:
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
The reason that the error occurs, is the state of the FtpWebResponse object, which is disposed; and has the StatusCode = ClosingData. When I try to read the stream in that state, I get the error you are experiencing. In the using block before, the StatusCode = OpeningData.
However, if you just change a couple of lines to:
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A
Console.WriteLine(read1.ReadToEnd());
Console.WriteLine("Directory is compleate,status(0)", res.StatusDescription);
}
When entering this using scope, the StatusCode = OpeningData, and stream is available and readable. When exiting the scope, the StatusCode = ClosingData, and stream will not be readable.
Hope this make some sense, and correct me if I'm wrong. :-)
With these small changes your code will run as expected. However you should look into the pattern #DmitryBychenko proposes. That way you will have access to the resources within the scope that they're needed, and disposed afterwards.

How can I combine my FTP queries?

My program has several times where it queries an FTP server to read and upload information. How can I combine all these into one FTP class to handle everything?
private static void UploadToFTP(string[] FTPSettings)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(FTPSettings[0]);
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Credentials = new NetworkCredential(FTPSettings[1], FTPSettings[2]);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
}
catch
{
}
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(FTPSettings[0] + Path.GetFileName(file));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(FTPSettings[1], FTPSettings[2]);
StreamReader source = new StreamReader(file);
byte[] fileContents = Encoding.UTF8.GetBytes(source.ReadToEnd());
source.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
RegenLog();
}
catch (Exception e)
{
File.AppendAllText(file, string.Format("{0}{0}Upload Failed - ({2}) - {1}{0}", nl, System.DateTime.Now, e.Message.ToString()));
}
}
private static void CheckBlacklist(string[] FTPSettings)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(FTPSettings[0] + "blacklist.txt");
request.Credentials = new NetworkCredential(FTPSettings[1], FTPSettings[2]);
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (TextReader reader = new StreamReader(stream))
{
string blacklist = reader.ReadToEnd();
if (blacklist.Contains(Environment.UserName))
{
File.AppendAllText(file, string.Format("{0}{0}Logger terminated - ({2}) - {1}{0}", nl, System.DateTime.Now, "Blacklisted"));
uninstall = true;
}
}
}
}
}
catch (Exception e)
{
File.AppendAllText(file, string.Format("{0}{0}FTP Error - ({2}) - {1}{0}", nl, System.DateTime.Now, e.Message.ToString()));
}
}
private static void CheckUpdate(string[] FTPSettings)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(FTPSettings[0] + "update.txt");
request.Credentials = new NetworkCredential(FTPSettings[1], FTPSettings[2]);
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (TextReader reader = new StreamReader(stream))
{
string newVersion = reader.ReadToEnd();
if (newVersion != version)
{
update = true;
}
}
}
}
}
catch (Exception e)
{
File.AppendAllText(file, string.Format("{0}{0}FTP Error - ({2}) - {1}{0}", nl, System.DateTime.Now, e.Message.ToString()));
}
}
I know my code is also a bit inconsistent and messy, however this is my first time working with FTP in C#. Please give any advice you have!
An ideal option would be to use a "manager" type of class, implementing the IDisposable interface.
Let it have some internal fields (which get initialized in the constructor) and one connection (also initialized in the constructor)
Every method should check if the connection is alive and, if it is, perform the operation; otherwise, try to restore it then throw an exception.
In Dispose method, you close the connection.
This should give you an idea on how it may look:
// Partial class declaration
class FTPManager : IDisposable
{
void Dispose();
FTPManager(string host, string username, string password)
void UploadFile(string remoteDir, string localfile);
void CreateDirectory(string remotePath);
void DeleteFile(string remotePath);
}
// and here I use it:
void Main()
{
using (var manager = new FTPManager("ftp.somehosting.org","login","password")) {
manager.CreateDirectory("/newfolder/");
manager.UploadFile("/newfolder/","C:\\Somefile.txt");
manager.DeleteFile("/newfolder/anotherfile.txt");
}
}
You might want to look at the WinSCP library.
WinSCP has a lot of features and supports more secure protocols than (inherently unsecure FTP).
Recent releases even feature a scripting mechanism.
You should use other FTP .NET library (there is a number of them over the internet, free ones and commercial as well), which allow to do all the commands in one connection. That would work much faster.

c# httpwebrequest getResponse() freezes and hangs my program

I was trying to use httpwebrequest to use a rest like service on a remote server and from the first execution itself, my code was hanging the program. Then I tried it as a console application to make sure it has nothing to do with the program itself but no luck!
string credentialsJson = #"{""username"":""test"",
""password"":""test""
}";
int tmp = ServicePointManager.DefaultConnectionLimit;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"https://qrua.com/qr/service" + #"/auth/login");
request.Method = "POST";
request.KeepAlive = true;
request.Timeout = 50000 ;
request.CookieContainer = new CookieContainer();
request.ContentType = "application/json";
try
{
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(credentialsJson);
}
catch (Exception e)
{
Console.WriteLine("EXCEPTION:" + e.Message);
}
//WebResponse response = request.GetResponse();
try
{
using (WebResponse response = (HttpWebResponse)request.GetResponse())
{
Console.WriteLine("request:\n" + request.ToString() + "\nresponse:\n" + response.ContentLength);
response.Close();
}
}
catch (Exception e)
{
Console.WriteLine("EXCEPTION: in sending http request:" + " \nError message:" + e.Message);
}
Tried several things from different forums but it doesnt help. Even a simple console app with the above code hangs the console indefinitely! Any help would be great..
Thanks
You're never closing the StreamWriter... so I suspect it's not being flushed. Admittedly I'd expect an error from the server instead of just a hang, but it's worth looking at.
Btw, you don't need to close the response and dispose it. Just the using statement is enough.
There's not much you can do if the remote server is not responding other than defining a Timeout and catch the exception as you did in order to inform the user that the operation cannot complete because the remote site didn't respond:
var request = (HttpWebRequest)WebRequest.Create("https://qrua.com/qr/service/auth/login");
request.Timeout = 5000;
// If the server doesn't respond within 5 seconds you might catch the timeout exception
using (var response = request.GetResponse())
{
}
If you don't want to freeze the UI you could use the async version: BeginGetResponse
Try specifying request.ContentLength.
Before doing:
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(credentialsJson);
Try something like this:
using (MemoryStream stream = new MemoryStream())
{
using (var writer = StreamWriter writer = new StreamWriter(stream))
{
writer.Write(credentialsJson);
writer.Close();
}
request.ContentLength = stream.Length;
}

Categories