I am trying to download images from the site. The code which I am using is working fine while the image is available. If the image it not available it is creating a problem. How to validate availability of the image?
Code:
Method 1:
WebRequest requestPic = WebRequest.Create(imageUrl);
WebResponse responsePic = requestPic.GetResponse();
Image webImage = Image.FromStream(responsePic.GetResponseStream()); // Error
webImage.Save("D:\\Images\\Book\\" + fileName + ".jpg");
Method 2:
WebClient client = new WebClient();
Stream stream = client.OpenRead(imageUrl);
bitmap = new Bitmap(stream); // Error : Parameter is not valid.
stream.Flush();
stream.Close();
client.dispose();
if (bitmap != null)
{
bitmap.Save("D:\\Images\\" + fileName + ".jpg");
}
Edit:
Stream has the following statements:
Length '((System.Net.ConnectStream)(str)).Length' threw an exception of type 'System.NotSupportedException' long {System.NotSupportedException}
Position '((System.Net.ConnectStream)(str)).Position' threw an exception of type 'System.NotSupportedException' long {System.NotSupportedException}
ReadTimeout 300000 int
WriteTimeout 300000 int
There is no need to involve any image classes, you can simply call WebClient.DownloadFile:
string localFilename = #"c:\localpath\tofile.jpg";
using(WebClient client = new WebClient())
{
client.DownloadFile("http://www.example.com/image.jpg", localFilename);
}
Update
Since you will want to check whether the file exists and download the file if it does, it's better to do this within the same request. So here is a method that will do that:
private static void DownloadRemoteImageFile(string uri, string fileName)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Check that the remote file was found. The ContentType
// check is performed since a request for a non-existent
// image file might be redirected to a 404-page, which would
// yield the StatusCode "OK", even though the image was not
// found.
if ((response.StatusCode == HttpStatusCode.OK ||
response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.Redirect) &&
response.ContentType.StartsWith("image",StringComparison.OrdinalIgnoreCase))
{
// if the remote file was found, download oit
using (Stream inputStream = response.GetResponseStream())
using (Stream outputStream = File.OpenWrite(fileName))
{
byte[] buffer = new byte[4096];
int bytesRead;
do
{
bytesRead = inputStream.Read(buffer, 0, buffer.Length);
outputStream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
}
}
In brief, it makes a request for the file, verifies that the response code is one of OK, Moved or Redirect and also that the ContentType is an image. If those conditions are true, the file is downloaded.
I have used Fredrik's code above in a project with some slight modifications, thought I'd share:
private static bool DownloadRemoteImageFile(string uri, string fileName)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (Exception)
{
return false;
}
// Check that the remote file was found. The ContentType
// check is performed since a request for a non-existent
// image file might be redirected to a 404-page, which would
// yield the StatusCode "OK", even though the image was not
// found.
if ((response.StatusCode == HttpStatusCode.OK ||
response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.Redirect) &&
response.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
{
// if the remote file was found, download it
using (Stream inputStream = response.GetResponseStream())
using (Stream outputStream = File.OpenWrite(fileName))
{
byte[] buffer = new byte[4096];
int bytesRead;
do
{
bytesRead = inputStream.Read(buffer, 0, buffer.Length);
outputStream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
return true;
}
else
return false;
}
Main changes are:
using a try/catch for the GetResponse() as I was running into an exception when the remote file returned 404
returning a boolean
Also possible to use DownloadData method
private byte[] GetImage(string iconPath)
{
using (WebClient client = new WebClient())
{
byte[] pic = client.DownloadData(iconPath);
//string checkPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +#"\1.png";
//File.WriteAllBytes(checkPath, pic);
return pic;
}
}
private static void DownloadRemoteImageFile(string uri, string fileName)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if ((response.StatusCode == HttpStatusCode.OK ||
response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.Redirect) &&
response.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
{
using (Stream inputStream = response.GetResponseStream())
using (Stream outputStream = File.OpenWrite(fileName))
{
byte[] buffer = new byte[4096];
int bytesRead;
do
{
bytesRead = inputStream.Read(buffer, 0, buffer.Length);
outputStream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
}
}
The best practice to download an image from Server or from Website and store it locally.
WebClient client=new Webclient();
client.DownloadFile("WebSite URL","C:\\....image.jpg");
client.Dispose();
You can use this code
using (WebClient client = new WebClient()) {
Stream stream = client.OpenRead(imgUrl);
if (stream != null) {
Bitmap bitmap = new Bitmap(stream);
ImageFormat imageFormat = ImageFormat.Jpeg;
if (bitmap.RawFormat.Equals(ImageFormat.Png)) {
imageFormat = ImageFormat.Png;
}
else if (bitmap.RawFormat.Equals(ImageFormat.Bmp)) {
imageFormat = ImageFormat.Bmp;
}
else if (bitmap.RawFormat.Equals(ImageFormat.Gif)) {
imageFormat = ImageFormat.Gif;
}
else if (bitmap.RawFormat.Equals(ImageFormat.Tiff)) {
imageFormat = ImageFormat.Tiff;
}
bitmap.Save(fileName, imageFormat);
stream.Flush();
stream.Close();
client.Dispose();
}
}
Project available at: github
Related
I'm reading a large file into a stream, of which I'm filling a 4k buffer which I'm writing to a HttpWebRequest stream.
For some reason I'm getting out of memory exceptions, not sure why.
Am I doing something incorrectly?
My method:
public void StreamBlob(FileInfo file, Uri blobContainerSasUri, string containerName)
{
try
{
var method = "PUT";
var token = blobContainerSasUri.Query;
var requestUri =
new Uri($"https://{blobContainerSasUri.Host}/{containerName}/{string.Concat(file.Name, token)}");
using (var fileStream = file.OpenRead())
{
var request = (HttpWebRequest) WebRequest.Create(requestUri);
request.Method = method;
request.ContentType = MimeMapping.GetMimeMapping(file.FullName);
request.Headers.Add("x-ms-blob-type", "BlockBlob");
request.ContentLength = fileStream.Length;
request.AllowWriteStreamBuffering = false;
using (var serverStream = request.GetRequestStream())
{
var buffer = new byte[4096];
while (true)
{
var bytesRead = fileStream.Read(buffer, 0, buffer.Length);
if (bytesRead > 0)
serverStream.Write(buffer, 0, bytesRead);
else
break;
}
}
using (var resp = (HttpWebResponse) request.GetResponse())
{
try
{
if (resp.StatusCode == HttpStatusCode.OK)
_logger.Log.Info("Received http response {resp}");
}
catch (Exception ex)
{
_logger.Log.Warn($"Received http response {resp}", ex)
}
}
}
}
catch (Exception ex)
{
_logger.Log.Warn($"Error uploading {file.Fullname}, ex")
}
I'm using the following code for getting an IP camera stream :
private void Display()
{
try
{
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Credentials = new NetworkCredential("username", "password");
HttpWebResponse myHttpWebResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream receiveStream = myHttpWebResponse.GetResponseStream();
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.AppendHeader("Content-Type", "video/mp4");
using (BinaryReader binaryReader = new BinaryReader(receiveStream))
{
byte[] buffer = new byte[100000];
while (true)
{
int nbrByte = receiveStream.Read(buffer, 0, buffer.Length);
if (nbrByte == 0)
break;
Response.OutputStream.Write(buffer, 0, nbrByte);
Response.Clear();
//Response.Flush();
}
}
}
catch (Exception ex)
{
string errMsg = ex.Message;
}
}
Nothing is happening when I run the code. Using the browser and after login I can see the video. Am I missing something?
Guys this the code to store file on ftp. Can any one reconfigure this code so that it stores the contents of the richtextbox in windows forms I'm writing anything on richtextbox when I click button it should store directly ftp.
{
Stream requestStream = null;
FileStream fileStream = null;
FtpWebResponse uploadResponse = null;
try
{
uploadUrl = "ftp://ftp.personalwebars.com/ATM/";
fileName = txtTitle.Text + ".txt";
FtpWebRequest uploadRequest = (FtpWebRequest)WebRequest.Create(uploadUrl + #"/" + fileName);
uploadRequest.Method = WebRequestMethods.Ftp.UploadFile;
//Since the FTP you are downloading to is secure, send
//in user name and password to be able upload the file
ICredentials credentials = new NetworkCredential(user, pswd);
uploadRequest.Credentials = credentials;
//UploadFile is not supported through an Http proxy
//so we disable the proxy for this request.
uploadRequest.Proxy = null;
//uploadRequest.UsePassive = false; <--found from another forum and did not make a difference
requestStream = uploadRequest.GetRequestStream();
byte[] buffer = new byte[1024];
int bytesRead;
while (true)
{
bytesRead = fileStream.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
break;
requestStream.Write(buffer, 0, bytesRead);
}
//The request stream must be closed before getting
//the response.
requestStream.Close();
uploadResponse =
(FtpWebResponse)uploadRequest.GetResponse();
lblAuthentication.Text = "Your solution has been submitted in txt Mode. Thank You";
}
catch (WebException ex)
{
}
finally
{
if (uploadResponse != null)
uploadResponse.Close();
if (fileStream != null)
fileStream.Close();
if (requestStream != null)
requestStream.Close();
}
}
Try this, extract the string from the text box and pass it in as the content parameter,
public void Send(string url, string fileName, string content, string user, string password)
{
byte[] bytes = Encoding.ASCII.GetBytes(content)
var request = (FtpWebRequest) WebRequest.Create(new Uri(url + #"/" + fileName));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UsePassive = false;
request.Credentials = new NetworkCredential(user, password);
request.ContentLength = bytes.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
var response = (FtpWebResponse) request.GetResponse();
if (response != null) response.Close();
}
This is the code:
HttpWebRequest request;
int currentIndex = 0;
void fileDownloadRadar(string uri, string fileName)
{
if (splash != null)
{
if (!splash.IsDisposed)
splash.UpdateProgressBar(0);
}
/*_request = WebRequest.Create(uri) as HttpWebRequest;
_request.CookieContainer = new CookieContainer();
_request.AllowAutoRedirect = true;
_responseAsyncResult = _request.BeginGetResponse(ResponseCallback, null);*/
request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
request.CookieContainer = new CookieContainer();
request.AllowAutoRedirect = true;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
long contentLength = response.ContentLength;
if (response.ContentType == "")
{
Logger.Write("ContentType is Empty download was not fine !!!!!");
}
if ((response.StatusCode == HttpStatusCode.OK ||
response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.Redirect) &&
response.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
{
Logger.Write("ContentType is not empty meaning download is fine");
using (Stream inputStream = response.GetResponseStream())
using (Stream outputStream = File.OpenWrite(fileName))
{
byte[] buffer = new byte[4096];
int bytesRead;
do
{
bytesRead = inputStream.Read(buffer, 0, buffer.Length);
currentIndex += bytesRead;
double percentage = (double)currentIndex / contentLength;
if (splash != null)
{
if (!splash.IsDisposed)
splash.UpdateProgressBar((int)(percentage * 100));
}
outputStream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
if (splash != null)
{
if (!splash.IsDisposed)
{
splash.UpdateProgressBar(100);
}
}
}
}
else
{
timer1.Stop();
timer3.Start();
}
if (splash == null)
FinishWebRequest();
}
The exception is on the line:
bytesRead = inputStream.Read(buffer, 0, buffer.Length);
The exception is: WebException
The operation has timed out
I see that when the exception happened the variable bytesRead value is 1360
And buffer values is 4096
System.Net.WebException occurred
HResult=-2146233079
Message=The operation has timed out.
Source=System
StackTrace:
at System.Net.ConnectStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at mws.Form1.fileDownloadRadar(String uri, String fileName) in d:\C-Sharp\Download File\Downloading-File-Project-Version-012\Downloading File\Form1.cs:line 914
InnerException:
Line 914 is:
bytesRead = inputStream.Read(buffer, 0, buffer.Length);
Maybe i should put try and catch somewhere ?
My code is downloading a file then a timer is running when the timer count 5 minutes it's downloading the same file again and so on over again nonstop every 5 minutes i'm calling this method to download the file.
EDIT this is my code after changed it according to the answers:
HttpWebRequest request;
int currentIndex = 0;
void fileDownloadRadar(string uri, string fileName)
{
if (splash != null)
{
if (!splash.IsDisposed)
splash.UpdateProgressBar(0);
}
try
{
request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
request.Timeout = 10000;
request.CookieContainer = new CookieContainer();
request.AllowAutoRedirect = true;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
long contentLength = response.ContentLength;
if (response.ContentType == "")
{
Logger.Write("ContentType is Empty download was not fine !!!!!");
}
if ((response.StatusCode == HttpStatusCode.OK ||
response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.Redirect) &&
response.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
{
Logger.Write("ContentType is not empty meaning download is fine");
using (Stream inputStream = response.GetResponseStream())
using (Stream outputStream = File.OpenWrite(fileName))
{
byte[] buffer = new byte[4096];
int bytesRead;
do
{
bytesRead = inputStream.Read(buffer, 0, buffer.Length);
currentIndex += bytesRead;
double percentage = (double)currentIndex / contentLength;
if (splash != null)
{
if (!splash.IsDisposed)
splash.UpdateProgressBar((int)(percentage * 100));
}
outputStream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
if (splash != null)
{
if (!splash.IsDisposed)
{
splash.UpdateProgressBar(100);
}
}
}
}
else
{
timer1.Stop();
timer3.Start();
}
if (splash == null)
FinishWebRequest();
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.Timeout)
{
Logger.Write(ex.Status.ToString());
}
}
}
But after it was working fine for maybe an hour or so and downloaded the file few times now i got the exception time out again:
The operation has timed out
This time on the line:
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
And the exception message:
System.Net.WebException occurred
HResult=-2146233079
Message=The operation has timed out
Source=System
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at mws.Form1.fileDownloadRadar(String uri, String fileName) in d:\C-Sharp\Download File\Downloading-File-Project-Version-012\Downloading File\Form1.cs:line 899
InnerException:
I changed the response and using the using
Also added: request.Timeout = 10000;
And added also try and catch.
The timeouts you are seeing are caused by ServicePointManager - class that manages the collection of ServicePoint objects which provides connection management for HTTP connections.
In short, whenever you create a request and the response, the important thing is to call the Close() method on your response object. If not, it will prevent any of the connections in the ServicePoint object from being freed, so at some point, after you have made the critical number of request, no additional requests can be served and you will experience the timeouts.
For more in depth information check out this article: http://blogs.msdn.com/b/jpsanders/archive/2009/05/20/understanding-maxservicepointidletime-and-defaultconnectionlimit.aspx
HttpWebRequest req = CreateRequest();
HttpWebResponse res = req.GetResponse() as HttpWebResponse;
...
res.Close(); //you should always close the response
EDIT:
as #Kevin said in the comment, another solution would be to wrap the response in a using statement and that would automatically close the connection:
using(HttpWebResponse res = req.GetResponse() as HttpWebResponse)
{
...
}
The first step is to put your code inside try..catch
try
{
//code
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.Timeout)
{
//log your exception
}
}
Then wrap the web response with a using block because it automatically call close and also dispose the object
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
//your code
}
Lastly, I see in your code you have attempted to use asynchronous request, maybe you can consider that if you're dealing with huge files to deal with a timeout issue. Hope it helps.
System.Net.WebException: The operation has timed out
This may fit for your problem, as it is regarded to a TimeOut Exception.
The most helpful answer relates to:
https://msdn.microsoft.com/en-us/library/system.net.webrequest.timeout.aspx
I am writing url redirector. Now I am struggling with this:
Let's say I have this method:
public FileResult ImageRedirect(string url)
and I pass this string as an input: http://someurl.com/somedirectory/someimage.someExtension.
Now, I want my method to download that image from someurl, and return it as a File(). How can I do this?
Use WebClient class to download the file from the remote url and then return it using the Controller.File method. DownLoadData method in WebClient class will do the trick for you.
So you can write an action method like this which accepts the fileName(url to the file)
public ActionResult GetImage(string fileName)
{
if (!String.IsNullOrEmpty(fileName))
{
using (WebClient wc = new WebClient())
{
var byteArr= wc.DownloadData(fileName);
return File(byteArr, "image/png");
}
}
return Content("No file name provided");
}
So you can execute this by calling
yoursitename/yourController/GetImage?fileName="http://somesite.com/logo.png
Because you are potentially allowing user to make your server to download any file on the web, I think you WANT to limit the maximum download file size.
To do so, you can use this code :
public static MemoryStream downloadFile(string url, Int64 fileMaxKbSize = 1024)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(url));
webRequest.Credentials = CredentialCache.DefaultCredentials;
webRequest.KeepAlive = true;
webRequest.Method = "GET";
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
Int64 fileSize = webResponse.ContentLength;
if (fileSize < fileMaxKbSize * 1024)
{
// Download the file
Stream receiveStream = webResponse.GetResponseStream();
MemoryStream m = new MemoryStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = receiveStream.Read(buffer, 0, buffer.Length)) != 0 && bytesRead <= fileMaxKbSize * 1024)
{
m.Write(buffer, 0, bytesRead);
}
// Or using statement instead
m.Position = 0;
webResponse.Close();
return m;
}
return null;
}
catch (Exception ex)
{
// proper handling
}
return null;
}
And in your case, to be use like this :
public ActionResult GetImage(string fileName)
{
if (!String.IsNullOrEmpty(fileName))
{
return File(downloadFile(fileName, 2048), "image/png");
}
return Content("No file name provided");
}
fileMaxKbSize represents the maximum size allowed in kb (default is 1Mb)