I have a webform application written in C# and what I want to do is after the user submits a HTML form with an image, I send that image to a WCF Rest service also written in C#.
The problem is when I get the image in the web service this is corrupted.
I guess that the problem is that I don't encode the file properly, but after days of reading on internet I haven't found a clue.
Webform code:
protected void Page_Load(object sender, EventArgs e)
{
HttpPostedFile image = Request.Files["imagen"];
string serverResponse = Send("mywebservice/postimage", "POST", Encoding.UTF8.GetBytes(StreamToString(image.InputStream)));
}
Edit (this way worked)
protected void Page_Load(object sender, EventArgs e)
{
HttpPostedFile image = Request.Files["imagen"];
MemoryStream ms = new MemoryStream();
image.InputStream.CopyTo(ms);
byte[] bytes = ms.ToArray();
string serverResponse = Send("mywebservice/postimage", "POST", bytes);
}
public int Send(string url, string method, byte[] data)
{
string serverResponse = "";
HttpWebRequest newRequest = (HttpWebRequest)WebRequest.Create(url);
newRequest.ContentType = "image/jpeg";
newRequest.Method = method;
newRequest.Timeout = 10000;
if (newRequest.Method == "POST" || newRequest.Method == "PUT")
{
Stream reqStream = newRequest.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
}
WSMessageEnt wsMessageEnt = new WSMessageEnt();
try
{
HttpWebResponse webResponse;
webResponse = (HttpWebResponse)newRequest.GetResponse();
Stream dataStream = webResponse.GetResponseStream();
serverResponse = new StreamReader(dataStream).ReadToEnd();
}
catch (WebException we)
{
}
return serverResponse;
}
public static string StreamToString(Stream data)
{
StreamReader reader = new StreamReader(data);
string body = reader.ReadToEnd();
reader.Close();
reader.Dispose();
return body;
}
Webservice code:
[WebInvoke(UriTemplate = "upload-user-image", Method = "POST")]
public Stream UploadUserImage(Stream streamdata)
{
System.Drawing.Image img = System.Drawing.Image.FromStream(streamImagen, true);
// here I get a format error
}
Possibly one problem: you're converting a stream of bytes, into a string, then back to a stream of bytes. The image bytes are arbitrary bytes, which may or may not map to a string, and the encoding you're using in one conversion (Encoding.Default) may not be the same as the one used in the other (Encoding.UTF8).
Instead of doing this:
Encoding.UTF8.GetBytes(StreamToString(image.InputStream))
Try doing something like
MemoryStream ms = new MemoryStream();
image.InputStream.CopyTo(ms);
byte[] bytes = ms.ToArray();
Or just pass the stream to Send and copy it to the request stream.
Related
I am trying to make a CLR with .NET 2.0 integrated into MS SQL Server 2008. I call an API with and I should receive a .zip as response. I store the response into a Stream and I want to export this file to a physical .zip file.
I tried exporting the file with C# and SQL (BCB OR OLE) and all resulted into a corrupted file. So, I believe I am doing something wrong with in the making of the stream.
The C# code is the following:
private static byte[] GetStreamFileResult(Cookie loginCookie, Guid fileGuid, String baseUri)
{
byte[] output = null;
//String result = null;
string url = "some url"
CookieContainer cookies = new CookieContainer();
cookies.Add(new Uri(url), loginCookie);
WebRequest request = WebRequest.Create(url);
(request as HttpWebRequest).CookieContainer = cookies;
WebResponse response = request.GetResponse();
HttpWebResponse resp = response as HttpWebResponse;
Stream dataStream = response.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
CopyStream(dataStream, ms);
output = ms.ToArray();
}
dataStream.Close();
response.Close();
return output;
}
The C# code to export the zip is the following:
File.WriteAllBytes("C:\\folder\\t.zip", stream); // Requires System.IO
The copy from stream to stream:
public static void CopyStream(Stream input, Stream output)
{
if (input != null)
{
using (StreamReader reader = new StreamReader(input))
using (StreamWriter writer = new StreamWriter(output))
{
writer.Write(reader.ReadToEnd());
}
}
}
Your CopyStream is broken. You need to talk binary. You're currently treating binary zip data as though it were text:
byte[] buffer = new byte[2048];
int bytesRead;
while((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0) {
output.Write(buffer, 0, bytesRead);
}
public static string GetAvatar()
{
logger.Info("Start--GetAvatar");//aatif
// string headerText = "Bearer " + token;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://api.mxit.com/user/public/avatar/id");
//request.Method = method;
//request.Headers.Add(HttpRequestHeader.Authorization, headerText);
//if (contentType != null)
//{
// request.ContentType = contentType;
//}
string method = "GET";
if (method == "GET")
{
try
{
WebResponse response = request.GetResponse(); // Byte Stream
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
string JsonGET = responseFromServer.ToString();
// Avatar res = JsonConvert.DeserializeObject<Avatar>(JsonGET);
reader.Close();
dataStream.Close();
response.Close();
logger.Info("End--GetAvatar");//aatif
return JsonGET;
}
catch (Exception ex)
{
logger.Error("CacheData.GetAvatar():" + ex.StackTrace); /// Aatif
}
}
logger.Info("End--GetAvatar"); ///aatif
return null;
}
string avatar = MURLEngine.GetAvatar();
Showing Image in front end:
<span id="ProfileImage">
<img src="data:image/png;base64,#Model.avatarimage" />
</span>
How do i show the byte stream image on the front end? I am unable to do so right now.
You're close. Convert to base64.
(The other answers don't directly relate to your need for a WebRequest.)
public static string GetAvatar()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://api.mxit.com/user/public/avatar/vini.katyal");
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
MemoryStream ms = new MemoryStream();
responseStream.CopyTo(ms);
byte[] buffer = ms.ToArray();
string result = Convert.ToBase64String(buffer);
response.Close();
responseStream.Close();
return result;
}
I suggest you create a GET method in your controller which accepts an id of your row or something. Based on that just fetch the byte array and send it back to the as an contentresult. Here is an example for that:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Image(int id)
{
byte[] byteArray = _imageRepository.GetImage(id);
return new FileContentResult(byteArray, "image/jpeg");
}
In the view you can call this controller method in following way:
<img src="Image/1234" alt="Image 1234"/>
Try to use Convert class methods. You can make use of Convert.ToBase64String method to convert a byte array to base64 string representation of the image.
Example from MSDN:
try {
inFile = new System.IO.FileStream(inputFileName,
System.IO.FileMode.Open,
System.IO.FileAccess.Read);
binaryData = new Byte[inFile.Length];
long bytesRead = inFile.Read(binaryData, 0,
(int)inFile.Length);
inFile.Close();
}
catch (System.Exception exp) {
// Error creating stream or reading from it.
System.Console.WriteLine("{0}", exp.Message);
return;
}
// Convert the binary input into Base64 UUEncoded output.
string base64String;
try {
base64String =
System.Convert.ToBase64String(binaryData,
0,
binaryData.Length);
}
catch (System.ArgumentNullException) {
System.Console.WriteLine("Binary data array is null.");
return;
}
Here is another example that I found.
I solved the issue:
WebResponse response = request.GetResponse();
byte[] b = null;
using (Stream stream = response.GetResponseStream())
using (MemoryStream ms = new MemoryStream())
{
int count = 0;
do
{
byte[] buf = new byte[1024];
count = stream.Read(buf, 0, 1024);
ms.Write(buf, 0, count);
} while (stream.CanRead && count > 0);
b = ms.ToArray();
}
return Convert.ToBase64String(b);
I firstly convert the response to Stream and then to Byte array then to the base64 string
I am generating an ssrs report in my Silverlight application and I need to convert the ssrs report to RadPDFViewer control(telerik silverlight).
So I am saving the pdf file in the project folder using WCF.
Now i need to read the file again and bind it to Pdfviewer.
Saving happens asynchronously.
How should I wait untill the file is saved and then read from the folder?
Also, can you please show me how to read the PDF as a Memory stream.
I run the following code unsuccessfully.
public byte[] ReturnPdf(string requestUrl) {
HttpWebRequest req = null; var buf = new byte[1024];
try
{
req = (HttpWebRequest)WebRequest.Create(requestUrl);
req.Credentials = CredentialCache.DefaultCredentials;
req.Method = "GET"; var objResponse = req.GetResponse();
var stream = objResponse.GetResponseStream();
if (stream != null){BinaryReader br = new BinaryReader(stream);
buf = br.ReadBytes(1024);
} if
(stream != null) stream.Close();
}
catch Exception e){}return buf;
}
private void button2_Click(object sender, EventArgs e)
{
string baseUrl = "http://abc/ReportServer&rs:Command=Render&rs:ClearSession=true&rs:Format=PDF";
const string nullString = ":isnull=true";
byte[] o = ReturnPdf(baseUrl);
byte[] bytes = new byte[1024];
Stream s = new MemoryStream(bytes);
}
Write PDF Stream:
Write PDF stream to response stream
You could check to see if the file has been written completely.
How to test if a file is currently being written to
Or this might help:
How to check for file lock?
I want to use C# to convert a byteArray to base64string by using Convert.ToBase64String(), then I want to send this string to save using MySQL by sending post data to a PHP page. My problem is I can't convert this string back to a byteArray using this method as after this string is retrieved from the PHP page (after it got data from MySQL), it tells me that argument on method Convert.FromBase64String() was wrong.
I don't where is problem occurs, how can I solve it?
My code:
public static string BitmapToString(BitmapImage img)
{
try
{
WriteableBitmap bmp = new WriteableBitmap(img);
byte[] byteArray = null;
string str = null;
MemoryStream stream = new MemoryStream();
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
byteArray = stream.ToArray();
str = Convert.ToBase64String(byteArray);
return str;
}
catch (System.Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
return null;
}
public static BitmapImage StringToBitmap(string str)
{
try
{
byte[] byteArray = Convert.FromBase64String(str);
Stream memStream = new MemoryStream(byteArray);
BitmapImage img = null;
MemoryStream stream = new MemoryStream(byteArray);
stream.Seek(0, SeekOrigin.Begin);
img = new BitmapImage();
img.SetSource(stream);
return img;
}
catch (System.Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
return null;
}
Convert.FromBase64String() will work for Convert.ToBase64String() results but there can be inputs in your aplication which not converted to Base64String, those cases might fail.
This is not be a issue with those two methods. Check Convert.ToBase64String() result and what you get when you read it from database.
I'm working on a quick wrapper for the skydrive API in C#, but running into issues with downloading a file. For the first part of the file, everything comes through fine, but then there start to be differences in the file and shortly thereafter everything becomes null. I'm fairly sure that it's just me not reading the stream correctly.
This is the code I'm using to download the file:
public const string ApiVersion = "v5.0";
public const string BaseUrl = "https://apis.live.net/" + ApiVersion + "/";
public SkyDriveFile DownloadFile(SkyDriveFile file)
{
string uri = BaseUrl + file.ID + "/content";
byte[] contents = GetResponse(uri);
file.Contents = contents;
return file;
}
public byte[] GetResponse(string url)
{
checkToken();
Uri requestUri = new Uri(url + "?access_token=" + HttpUtility.UrlEncode(token.AccessToken));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
request.Method = WebRequestMethods.Http.Get;
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
byte[] contents = new byte[response.ContentLength];
responseStream.Read(contents, 0, (int)response.ContentLength);
return contents;
}
This is the image file I'm trying to download
And this is the image I am getting
These two images lead me to believe that I'm not waiting for the response to finish coming through, because the content-length is the same as the size of the image I'm expecting, but I'm not sure how to make my code wait for the entire response to come through or even really if that's the approach I need to take.
Here's my test code in case it's helpful
[TestMethod]
public void CanUploadAndDownloadFile()
{
var api = GetApi();
SkyDriveFolder folder = api.CreateFolder(null, "TestFolder", "Test Folder");
SkyDriveFile file = api.UploadFile(folder, TestImageFile, "TestImage.png");
file = api.DownloadFile(file);
api.DeleteFolder(folder);
byte[] contents = new byte[new FileInfo(TestImageFile).Length];
using (FileStream fstream = new FileStream(TestImageFile, FileMode.Open))
{
fstream.Read(contents, 0, contents.Length);
}
using (FileStream fstream = new FileStream(TestImageFile + "2", FileMode.CreateNew))
{
fstream.Write(file.Contents, 0, file.Contents.Length);
}
Assert.AreEqual(contents.Length, file.Contents.Length);
bool sameData = true;
for (int i = 0; i < contents.Length && sameData; i++)
{
sameData = contents[i] == file.Contents[i];
}
Assert.IsTrue(sameData);
}
It fails at Assert.IsTrue(sameData);
This is because you don't check the return value of responseStream.Read(contents, 0, (int)response.ContentLength);. Read doesn't ensure that it will read response.ContentLength bytes. Instead it returns the number of bytes read. You can use a loop or stream.CopyTo there.
Something like this:
WebResponse response = request.GetResponse();
MemoryStream m = new MemoryStream();
response.GetResponseStream().CopyTo(m);
byte[] contents = m.ToArray();
As LB already said, you need to continue to call Read() until you have read the entire stream.
Although Stream.CopyTo will copy the entire stream it does not ensure that read the number of bytes expected. The following method will solve this and raise an IOException if it does not read the length specified...
public static void Copy(Stream input, Stream output, long length)
{
byte[] bytes = new byte[65536];
long bytesRead = 0;
int len = 0;
while (0 != (len = input.Read(bytes, 0, Math.Min(bytes.Length, (int)Math.Min(int.MaxValue, length - bytesRead)))))
{
output.Write(bytes, 0, len);
bytesRead = bytesRead + len;
}
output.Flush();
if (bytesRead != length)
throw new IOException();
}