error resolving System.ArgumentException using wcf service - c#

I want to convert Image to Base64String format,For that I am using this code
string conversionData = imageToBase64("http//localhost/MyService/Images/myImage.png");
the code of "imageToBase64()" is
private string imageToBase64(string path)
{
using(Image image = Image.FromFile(path))
{
using(MemoryStream m = new MemoryStream())
{
byte[] imageBytes = m.ToArray();
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}
}
When I am passing path to this method I am getting the error "An exception of type 'System.ArgumentException' occered ...".
thanks in advance

take a look :https://stackoverflow.com/questions/21325661/convert-image-path-to-base64-string.You missed image.Save(m, image.RawFormat)
Hope it will help

The parameter of fromfile cannot be URI, otherwise an error will be reported.
The interface that accesses WCF will return stream. We need to use the Httpwebrequest request interface to receive its stream,then save it locally before using fromfile.Here is a Demo:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:8000/Service/GetImage?width=50&height=40");
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (File.Exists("d:\\name.png"))
File.Delete("d:\\name.png");
Stream outStream = System.IO.File.Create("d:\\name.png");
Stream inStream = response.GetResponseStream();
int l;
byte[] buffer = new byte[1024];
do
{
l = inStream.Read(buffer, 0, buffer.Length);
if (l > 0)
outStream.Write(buffer, 0, l);
}
while (l > 0);
outStream.Close();
inStream.Close();
Image image = Image.FromFile("d:\\name.png");

Related

Web service File Stream to Byte[] to FileStream to pdf failing C#

I am trying to create a web service that returns a pdf file as a byte[] and then the app that consumes it grabs the byte[] and saves it as a pdf file and then opens it. The file fails to open at the end.
Here is the Web Service that returns a byte[]
[WebMethod]
public byte[] XXXX(int fileID)
{
try
{
using (EntitiesModel dbContext = new EntitiesModel())
{
string fileFullPath = .....
.......
if (fileFullNamePath != null)
{
FileStream fileStream = new FileStream(fileFullNamePath, FileMode.Open, System.IO.FileAccess.Read);
int len = fileStream.Length.ToInt();
Byte[] documentContents = new byte[len];
fileStream.Read(documentContents, 0, len);
fileStream.Close();
return documentContents;
Then it is called from an app with the following code
string soap = "<?xml version=\"1.0\" encoding=\"utf - 8\"?>" +
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soap:Body>" +
"<XXXX xmlns=\"http://tempuri.org/\">" +
"<fileID>XXXXX</fileID>" +
"</XXXX>" +
"</soap:Body>" +
"</soap:Envelope>";
string localhostContext = #"http://localhost:3381/";
string webserviceAddress = #"XXXX/XXXX/XXXXX.asmx";
string url = localhostContext + webserviceAddress ;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "text/xml";
request.ContentLength = soap.Length;
request.Timeout = 20000;
request.Method = "POST";
using (Stream stream = request.GetRequestStream())
{
using (StreamWriter streamWriter = new StreamWriter(stream))
{
streamWriter.Write(soap); }
}
}
byte[] bytes;
try
{
WebResponse response = request.GetResponse();
bytes = ReadFully(response.GetResponseStream());
}
catch (Exception exception)
{
throw;
}
private byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16*1024];
using (MemoryStream memoryStream = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
memoryStream.Position = 0;
memoryStream.Write(buffer, 0, read);
}
return memoryStream.ToArray();
}
}
FileStream objfilestream =
new FileStream(fileName, FileMode.Create,FileAccess.ReadWrite);
objfilestream.Write(bytes, 0, bytes.Length);
objfilestream.Close();
var process = Process.Start(fileName);
The code runs fine and creates a pdf and then tries to open that pdf. But the file can not be opened. Adobe Acrobat gives the error
Adobe Acrobat Reader could not open XXX.pdf because it is either not a
supported file type or because the file has been damaged (for example, it
was sent as an email attachment and wasn't correctly decoded).
Because I am not getting an error in the code I am at a loss to know where the error is that is not creating the proper file.
There was an issue with the Stream variable called input was not giving length so I used Jon Skeet's suggestion here Stackoverflow:Creating a byte array from a stream
new byte[16*1024];
rather than
new byte[input.length]
There were three things wrong.
memoryStream.Position = 0;
in the while loop was problematic so I removed it.
Secondly when reading the stream. What it returned was the SOAP XMl message with the encoded base64 string in the the XXXXResult XML tag. So I had to extract that.
Finally I had to use
byte[] fileResultBytes = Convert.FromBase64String(resultString);
to get the byte[] from the resultString extracted from the SOAP message. In the test SOAP message, that can be generated locally, it tells you the type of this result string. I missed that initially.
Thanks to VC.One and CodeCaster for their correct suggestions.

Load an image from URL as base64 string

I am trying to load an image as a base 64 string so that i can show it in a html like this:
<html><body><img src="data:image/jpeg;base64,/></img></body></html>
Heres my code so far, but it does not really work:
public async static Task<string> getImage(string url)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.Accept = "data:image/jpg;charset=base64";
request.Credentials = new NetworkCredential(user, pw);
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
StreamReader sr = new StreamReader(response.GetResponseStream());
return sr.ReadToEnd();
}
I tried using this method i found elsewhere to encode the return-String as base64, but when placing it in a html the image just shows the typical placeholder.
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
EDIT:
Here is how the html looks:
It seems to me that you need to separate the base64 part, which is only needed in your HTML, from fetching the data from the response. Just fetch the data from the URL as binary data and convert that to base64. Using HttpClient makes this simple:
public async static Task<string> GetImageAsBase64Url(string url)
{
var credentials = new NetworkCredential(user, pw);
using (var handler = new HttpClientHandler { Credentials = credentials })
using (var client = new HttpClient(handler))
{
var bytes = await client.GetByteArrayAsync(url);
return "image/jpeg;base64," + Convert.ToBase64String(bytes);
}
}
This assumes the image always will be a JPEG. If it could sometimes be a different content type, you may well want to fetch the response as an HttpResponse and use that to propagate the content type.
I suspect you may want to add caching here as well :)
using (HttpClient client = new HttpClient())
{
try
{
using (Stream stream = await client.GetStreamAsync(uri))
{
if (stream == null)
return (Picture)null;
byte[] buffer = new byte[16384];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int num = await stream.ReadAsync(buffer, 0, buffer.Length, cancellation);
int read;
if ((read = num) > 0)
ms.Write(buffer, 0, read);
else
break;
}
imageData = Convert.ToBase64String(ms.ToArray());
}
buffer = (byte[])null;
}
}
catch (Exception ex)
{
}
}
You must first get the image from disk, then convert it to byte[] and then again to base64.
public string ImageToBase64(Image image, System.Drawing.Imaging.ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}

Unhandled System.ArgumentException.. Additional Information: Parameter is not valid

I have this code in c# that pulls images from database and shows them in PictureBox. Whenever I run code first, I get this error saying "An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll Additional information: Parameter is not valid." But if I terminate and rerun the program, it works just fine giving intended results. Here is part of the code that is giving me trouble:
private void buttonGetImage_Click(object sender, EventArgs e)
{
string baseUrl = "http://someurl";
HttpWebRequest request = null;
foreach (var fileName in fileNames)
{
string url = string.Format(baseUrl, fileName);
MessageBoxButtons buttons = MessageBoxButtons.OKCancel;
DialogResult result;
result = MessageBox.Show(url, fileName, buttons);
if (result == System.Windows.Forms.DialogResult.Cancel)
{
this.Close();
}
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
request.CookieContainer = container;
response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
byte[] buffer = new byte[10000000];
int read, total = 0;
while ((read = stream.Read(buffer, total, 1000)) != 0)
{
total += read;
}
MemoryStream ms = new MemoryStream(buffer, 0, total);
ms.Seek(0, SeekOrigin.Current);
Bitmap bmp = (Bitmap)Bitmap.FromStream(ms);
pictureBoxTabTwo.Image = bmp;
this.pictureBoxTabTwo.SizeMode = PictureBoxSizeMode.Zoom;
pictureBoxTabTwo.Image.Save("FormTwo.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
Can someone help me to figure out what can be done?
Error is showing me line --> Bitmap bmp = (Bitmap)Bitmap.FromStream(ms);
Instead of using Bitmap class I used Image class in my program. What I was doing here was taking a stream and putting it into a byte array. And again converting content of that array back to stream. Instead, I used
Image img = Image.FromStream(stream)
In this case You don't even have to use MemoryStream. It is working perfectly find for me now.
Hard to tell from your code what the problem could be, but likely the query you are making on the server returns an unexpected response in some circumstances. You'd be best to get a snapshot of the returned stream when things goes wrong. It will allow you to diagnose the problem and take appropriate measures.
You need to do proper object disposal. Otherwise, the underlying connection doesn't close until the garbage collector catches up with the object and that can cause problems. Also, in .NET 4.0 and higher you can use the CopyTo method on Streams.
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
request.CookieContainer = container;
using (response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
{
// All of this code is unnecessary if using .NET 4.0 or higher.
/*
byte[] buffer = new byte[10000000];
int read, total = 0;
while ((read = stream.Read(buffer, total, 1000)) != 0)
{
total += read;
}
MemoryStream ms = new MemoryStream(buffer, 0, total);
ms.Seek(0, SeekOrigin.Current);
*/
// Instead use the following
MemoryStream ms = new MemoryStream();
stream.CopyTo(ms);
Bitmap bmp = (Bitmap)Bitmap.FromStream(ms);
pictureBoxTabTwo.Image = bmp;
this.pictureBoxTabTwo.SizeMode = PictureBoxSizeMode.Zoom;
pictureBoxTabTwo.Image.Save("FormTwo.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
You can try it
pictureBox1.Image = new Bitmap(sourceBitmap);

Can't consume byte[] or stream from WCF to create an image

UPDATE: Got it! Answer posted below... I will clean up the question so it may be more useful to someone else.
I have a service that uses a library to generate thumbnails from html pages using a WebBrowser control. That works fine but I need to create a WCF service that allows you to pass in a uri, then the service converts that to a thumbnail and returns it. I've tried it as a Stream and a byte[]. It creates the image in the service, I save it as a file just to prove it, but when I consume it I get data (more than I send) and I am unable to save it as a viewable image. Any suggestions would be appreciated. I am not a WCF expert so I'm hoping I've just missed something that will be easy to spot.
Here is the service, it's hosted in a console app and the Main() procedure is included.
namespace RawImageService
{
[ServiceContract]
public interface IImageServer
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "/image/?uri={uri}")]
Stream HtmlToImage(string uri);
}
public class Service : IImageServer
{
public Stream HtmlToImage(string uri)
{
string path = #"D:\Templates\HtmlServiceImage.bmp";
if( File.Exists(path) )
File.Delete(path);
if (string.IsNullOrEmpty(uri))
{
return null;
}
else
{
if ((uri.IndexOf("file:", System.StringComparison.Ordinal) < 0) &&
(uri.IndexOf("http", System.StringComparison.Ordinal) < 0))
uri = "http://" + uri;
Thumbnail.Uri = uri;
try
{
Bitmap bitmap =
HtmlToThumbnail.WebsiteThumbnail.GetThumbnail(Thumbnail.Uri, Thumbnail.Width,
Thumbnail.Hight, Thumbnail.ThumbWidth,
Thumbnail.ThumbHight);
using (MemoryStream ms = new MemoryStream())
{
bitmap.Save(ms, ImageFormat.Jpeg);
bitmap.Save(path, ImageFormat.Jpeg);
ms.Position = 0;
WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
return ms;
}
}
catch (Exception)
{
throw;
}
return null;
}
}
static void Main(string[] args)
{
string baseAddress = "http://" + Environment.MachineName + ":8000/";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IImageServer), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Service is running");
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
}
Here is my attempt to consume the service:
private static void Main(string[] args)
{
string uri = string.Concat("http://localhost:8000",
string.Format("/image/?uri={0}", "file:///D:/Templates/Test4.htm"));
tryThis(uri);
}
public static void tryThis(string uri)
{
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
request.Method = "GET";
// Get response
using (WebResponse response = request.GetResponse() as WebResponse)
{
using (Stream stream = response.GetResponseStream())
{
byte[] buffer = new byte[response.ContentLength];
MemoryStream ms = new MemoryStream();
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = stream.Read(buffer, 0, buffer.Length);
totalBytesRead += bytesRead;
ms.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
string path = #"D:/templates/fs.jpg";
if (File.Exists(path))
File.Delete(path);
var fs = new FileStream(path, FileMode.Create);
fs.Write(ms.ToArray(), 0, totalBytesRead);
fs.Flush();
fs.Close();
}
}
}
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
There is nothing additional in the .config files. I'm going to start looking into that but my understanding is I can configure everything in the app itself.
I don't care which way I get it working, I just need to get it working. I appreciate any suggestions. Thanks.
I got the Stream method working. Here is the code. I can access it like this:
http://localhost:8000/image/?uri=file:///D:/Templates/Test4.htm
Here is the new method. If you replace the code above with this it works.
public Stream HtmlToImage(string uri)
{
string path = #"D:\Templates\HtmlServiceImage.bmp";
if( File.Exists(path) )
File.Delete(path);
if (string.IsNullOrEmpty(uri))
{
return null;
}
else
{
if ((uri.IndexOf("file:", System.StringComparison.Ordinal) < 0) &&
(uri.IndexOf("http", System.StringComparison.Ordinal) < 0))
uri = "http://" + uri;
Thumbnail.Uri = uri;
try
{
Bitmap bitmap =
HtmlToThumbnail.WebsiteThumbnail.GetThumbnail(Thumbnail.Uri, Thumbnail.Width,
Thumbnail.Hight, Thumbnail.ThumbWidth,
Thumbnail.ThumbHight);
MemoryStream ms = new MemoryStream();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Position = 0;
WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
return ms;
}
catch (Exception)
{
throw;
}
return null;
}
}

Read Http Request into Byte array

I'm developing a web page that needs to take an HTTP Post Request and read it into a byte array for further processing. I'm kind of stuck on how to do this, and I'm stumped on what is the best way to accomplish. Here is my code so far:
public override void ProcessRequest(HttpContext curContext)
{
if (curContext != null)
{
int totalBytes = curContext.Request.TotalBytes;
string encoding = curContext.Request.ContentEncoding.ToString();
int reqLength = curContext.Request.ContentLength;
long inputLength = curContext.Request.InputStream.Length;
Stream str = curContext.Request.InputStream;
}
}
I'm checking the length of the request and its total bytes which equals 128. Now do I just need to use a Stream object to get it into byte[] format? Am I going in the right direction? Not sure how to proceed. Any advice would be great. I need to get the entire HTTP request into byte[] field.
Thanks!
The simplest way is to copy it to a MemoryStream - then call ToArray if you need to.
If you're using .NET 4, that's really easy:
MemoryStream ms = new MemoryStream();
curContext.Request.InputStream.CopyTo(ms);
// If you need it...
byte[] data = ms.ToArray();
EDIT: If you're not using .NET 4, you can create your own implementation of CopyTo. Here's a version which acts as an extension method:
public static void CopyTo(this Stream source, Stream destination)
{
// TODO: Argument validation
byte[] buffer = new byte[16384]; // For example...
int bytesRead;
while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
{
destination.Write(buffer, 0, bytesRead);
}
}
You can just use WebClient for that...
WebClient c = new WebClient();
byte [] responseData = c.DownloadData(..)
Where .. is the URL address for the data.
I use MemoryStream and Response.GetResponseStream().CopyTo(stream)
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
myRequest.Method = "GET";
WebResponse myResponse = myRequest.GetResponse();
MemoryStream ms = new MemoryStream();
myResponse.GetResponseStream().CopyTo(ms);
byte[] data = ms.ToArray();
I have a function that does it, by sending in the response stream:
private byte[] ReadFully(Stream input)
{
try
{
int bytesBuffer = 1024;
byte[] buffer = new byte[bytesBuffer];
using (MemoryStream ms = new MemoryStream())
{
int readBytes;
while ((readBytes = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, readBytes);
}
return ms.ToArray();
}
}
catch (Exception ex)
{
// Exception handling here: Response.Write("Ex.: " + ex.Message);
}
}
Since you have Stream str = curContext.Request.InputStream;, you could then just do:
byte[] bytes = ReadFully(str);
If you had done this:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(someUri);
req.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
You would call it this way:
byte[] bytes = ReadFully(resp.GetResponseStream());
class WebFetch
{
static void Main(string[] args)
{
// used to build entire input
StringBuilder sb = new StringBuilder();
// used on each read operation
byte[] buf = new byte[8192];
// prepare the web page we will be asking for
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create(#"http://www.google.com/search?q=google");
// execute the request
HttpWebResponse response = (HttpWebResponse)
request.GetResponse();
// we will read data via the response stream
Stream resStream = response.GetResponseStream();
string tempString = null;
int count = 0;
do
{
// fill the buffer with data
count = resStream.Read(buf, 0, buf.Length);
// make sure we read some data
if (count != 0)
{
// translate from bytes to ASCII text
tempString = Encoding.ASCII.GetString(buf, 0, count);
// continue building the string
sb.Append(tempString);
}
}
while (count > 0); // any more data to read?
// print out page source
Console.WriteLine(sb.ToString());
Console.Read();
}
}
For all those cases when your context.Request.ContentLength is greather than zero, you can simply do:
byte[] contentBytes = context.Request.BinaryRead(context.Request.ContentLength);

Categories