I am trying to create a System.Drawing.Image object from a WebResponse's response stream. Here's what I'm doing:
using (WebResponse response = await request.GetResponseAsync())
{
using (Stream originalInputStream = response.GetResponseStream())
{
// some code that calls a 3rd party image resizer, passing in the original stream
ResizeImage(originalInputStream, out resizedOutputStream);
// manipulation of the resizedOutputStream
// now i want to create an image from the ORIGINAL stream
// ERROR HAPPENS HERE!!
using (Image image = Image.FromStream(originalInputStream))
{
// random code that doesn't get hit because of the error above
}
}
}
When the program tries to create the Image.FromStream() in the using statement, I get an error saying:
'Parameter is not valid.'
I assume this is because of the manipulation of the originalInputStream in the resizer function. I searched around and found that resetting the position of the stream can solve these issues. So I tried that, using both:
originalInputStream.Seek(0, SeekOrigin.Begin);
originalInputStream.Position = 0;
but both of those are erroring out as well, giving me an error message of:
Specified method is not supported.
When I try and create the Image.FromStream(), WITHOUT any of the preceding image resizing/stream manipulation... IT WORKS. But THEN, I cannot do anything else with the stream afterwards, or else it will error out as before. However, I need to do the manipulation, and also create the Image, so I'm stuck.
Is the best course of action to simply create another request? And just create the image from the new request's response stream? that just seems like bad practice, I don't know, I feel like what I'm doing should theoretically work and I'm probably just doing something dumb.
Thanks in advance for the help, let me know if I can provide any extra info.
Resetting the stream position does not work on the Stream base class. If you can read the response into a MemoryStream, then you will be able to manipulate the image as you please. Something like this could work:
using (WebResponse response = await request.GetResponseAsync())
{
using (Stream responseStream = response.GetResponseStream())
{
using (MemoryStream memStream = new MemoryStream())
{
responseStream.CopyTo(memStream);
// some code that calls a 3rd party image resizer, passing in the original stream
ResizeImage(memStream, out resizedOutputStream);
memStream.Seek(0, SeekOrigin.Begin);
// manipulation of the resizedOutputStream
// now i want to create an image from the ORIGINAL stream
using (Image image = Image.FromStream(memStream))
{
}
}
}
}
Related
I try converting image data from the database which is already in byte[] back to the image and I'm getting "invalid parameter error" using Image.FileStream.
Please, can anyone help me out with this?
I've tried working around the code using various methods and the last one is below in my code.
byte[] data = validaccount.FingerPrint;
try
{
using (MemoryStream strm = new MemoryStream())
{
strm.Write(data, 0, data.Length);
strm.Position = 0;
System.Drawing.Image img = System.Drawing.Image.FromStream(strm);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
bi.StreamSource = ms;
bi.EndInit();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
The code is supposed to convert the byte[] into an image.
According to the docs, Image.FromStream(stream) will throw an argument exception if "The stream does not have a valid image format". Have you verified the data is actually correct? If so, what type of image is it?
You're misusing your streams. You only need 1 memory stream and it has a constructor that takes a byte array (no need to write the bytes yourself). Be sure to wrap it in a using block (like you did for your first stream).
You may not want to use BitmapImage - that's for xaml/wpf apps. You probably want System.Drawing.Bitmap which inherits/extends System.Drawing.Image. Additionally, Bitmap has a constructor which takes a stream - no need to use FromStream.
Finally, Image (and hence Bitmap since Bitmap inherits Image) implements IDisposable, so you should also wrap it in a using block.
P.S. This is a duplicate question.
Though its not memory stream, this method has worked for me and if you browse SO for your question, some times MS does not work.
using System.Drawing;
var converterdImage = (Bitmap)((new ImageConverter()).ConvertFrom(byteArray));
Byte Array to Image Conversion
On my service I am trying to create and return a MemoryStream like this:
// Write data.
MemoryStream memoryStream = new MemoryStream();
using (StreamWriter txtwriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8))
{
string tempString = "Test";
txtwriter.Write(tempString);
txtwriter.WriteLine();
// End response.
memoryStream.Position = 0L;
response.ReportMemoryStream = memoryStream;
response.Length = memoryStream.Length;
return response;
}
Note: having the End response part outside the using statement causes a Cannot access a closed stream error.
My response is a simple DataContract. When I try to read this data in my client doing something like this:
// Write stream.
if (remoteReport.ReportMemoryStream != null)
{
remoteReport.ReportMemoryStream.WriteTo(Response.OutputStream);
}
I get again the same error about the stream being closed.
How can I fix this issue and why is my stream closing even though I'm not explicitly doing so?
replace:
response.ReportMemoryStream = memoryStream;
with
memoryStream.CopyTo(response.ReportMemoryStream);
now you are using reference type I think, and your using statment is just disposing stream you are using.
You'll need to flush your StreamWriter instance, so it writes to the MemoryStream instance -
txtwriter.Flush();
Then you'll need to remove the using block, so the txtwriter doesn't by default destroyes the memoryStream.
I know there are similar posts but I haven't got any answer for my problem and hence posting this.
I have a method that retrieves and returns image from a image path. Below is the code snippet I used. This fails in some cases as the image is lost after returning.
public static Image GetImageFromPicPath(string strUrl)
{
WebResponse wrFileResponse;
wrFileResponse = WebRequest.Create(strUrl).GetResponse();
using (Stream objWebStream = wrFileResponse.GetResponseStream())
{
return Image.FromStream(objWebStream);
}
}
If I use Bitmap class and return the image, metadata is lost.
If I use MemoryStream (as shown below) and I don't dispose MemoryStream it works . But there is possible memory leak here. If I use using block, the image is lost.
MemoryStream ms = new MemoryStream();
objWebStream.CopyTo(ms, 8192);
return System.Drawing.Image.FromStream(ms);
Can someone suggest me best approach to solve this issue.
Thanks in advance!!
This is why it's not working for you (from https://msdn.microsoft.com/en-us/library/93z9ee4x(v=vs.110).aspx) :
Here's a post that covers the issue a bit more: Loading an image from a stream without keeping the stream open
Try this:
public static Image GetImageFromPicPath(string strUrl)
{
using (WebResponse wrFileResponse = WebRequest.Create(strUrl).GetResponse())
using (Stream objWebStream = wrFileResponse.GetResponseStream())
{
MemoryStream ms = new MemoryStream();
objWebStream.CopyTo(ms, 8192);
return System.Drawing.Image.FromStream(ms);
}
}
In your consuming code do something like this:
using (var image = GetImageFromPicPath("http://imgur.com/123456.png"))
{
//use image
}
By wrapping "var image" in a using statement, Dispose() will be called on image which will also Dispose() and release the underlying MemoryStream in use by the Image.
Use the MemoryStream and don't explicitly close it. The Bitmap will close it in its Dispose method. There's no memory leak, as long as you remember to Dispose() the Bitmap when you're done with it. (And even if you didn't, the MemoryStream would eventually get garbage collected provided you let go of the Bitmap at some point and the Bitmap's the only thing holding a reference to it.)
https://support.microsoft.com/en-us/kb/814675
I have a PDF which is hosted in say http://test.com/mypdf.pdf.
How can I convert the PDF to Stream and then using this Stream convert it back to PDF.
I tried the following but got an exception(see image):
private static Stream ConvertToStream(string fileUrl)
{
HttpWebResponse aResponse = null;
try
{
HttpWebRequest aRequest = (HttpWebRequest)WebRequest.Create(fileUrl);
aResponse = (HttpWebResponse)aRequest.GetResponse();
}
catch (Exception ex)
{
}
return aResponse.GetResponseStream();
}
This will work:
private static Stream ConvertToStream(string fileUrl)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fileUrl);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
try {
MemoryStream mem = new MemoryStream();
Stream stream = response.GetResponseStream();
stream.CopyTo(mem,4096);
return mem;
} finally {
response.Close();
}
}
However you are entirely responsible for the lifetime of the returned memory stream.
A better approach is:
private static void ConvertToStream(string fileUrl, Stream stream)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fileUrl);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
try {
Stream response_stream = response.GetResponseStream();
response_stream.CopyTo(stream,4096);
} finally {
response.Close();
}
}
You can then do something like:
using (MemoryStream mem = new MemoryStream()) {
ConvertToStream('http://www.example.com/',mem);
mem.Seek(0,SeekOrigin.Begin);
... Do something else ...
}
You may also be able to return the response stream directly but you'd have to check on the lifetime of that, releasing the response may release the stream, hence the mem copy.
You may want to take a look at WebClient.DownloadFile.
You give it a URL and local file name and it saves the file straight to disk. Might save you a step or two.
You could also try WebClient.DownloadData which saves the file to an in-memory byte[].
EDIT
You did not specify the protocol of the web-service you are posting the file to. The simplest form (RESTful) would be just to POST the file to data to another URL. Here is how you would do that.
using (WebClient wc = new WebClient())
{
// copy data to byte[]
byte[] data = wc.DownloadData("http://somesite.com/your.pdf");
// POST data to another URL
wc.Headers.Add("Content-Type","application/pdf");
wc.UploadData("http://anothersite.com/your.pdf", data);
}
If you are using SOAP, you would have to convert the file to a Base64 string, but hopefully you are using a generated client which takes care of that for you. If you could elaborate on the type of web-service you are sending the file to, I could probably provide some more information..
I have this method:
public RasImage Load(Stream stream);
if I want to load a url like:
string _url = "http://localhost/Application1/Images/Icons/hand.jpg";
How can I make this url in to a stream and pass it into my load method?
Here's one way. I don't really know if it's the best way or not, but it works.
// requires System.Net namespace
WebRequest request = WebRequest.Create(_url);
using (var response = request.GetRespone())
using (var stream = response.GetResponseStream())
{
RasImage image = Load(stream);
}
UPDATE: It looks like in Silverlight, the WebRequest class has no GetResponse method; you've no choice but to do this asynchronously.
Below is some sample code illustrating how you might go about this. (I warn you: I wrote this just now, without putting much thought into how sensible it is. How you choose to implement this functionality would likely be quite different. Anyway, this should at least give you a general idea of what you need to do.)
WebRequest request = WebRequest.Create(_url);
IAsyncResult getResponseResult = request.BeginGetResponse(
result =>
{
using (var response = request.EndGetResponse(result))
using (var stream = response.GetResponseStream())
{
RasImage image = Load(stream);
// Do something with image.
}
},
null
);
Console.WriteLine("Waiting for response from '{0}'...", _url);
getResponseResult.AsyncWaitHandle.WaitOne();
Console.WriteLine("The stream has been loaded. Press Enter to quit.");
Console.ReadLine();
Dan's answer is a good one, though you're requesting from localhost. Is this a file you can access from the filesystem? If so, I think you should be able to just pass in a FileStream:
FileStream stream = new FileStream(#"\path\to\file", FileMode.Open);