How to get PDF back from a byte array - c#

What I’m trying to do is…
Let the user select a PDF file and some other files using a WCF…once they select the file…those files need to be moved from there to a remote server (company hosted). I’m trying to deserialize the data (reading it as bytes) and transferring it over. I created a Form just as a testing purpose and to see how my client is going to work.
When I get the file....I can display the file but I want to get the actual PDF back and I’m not being able to do that. I can open the file in notepad (but its in the byte format) and when I try to open it in PDF it says that the file format is not supported. I’m really confused and don’t know what needs to be done.
Your help will be really appreciated.
Code Snippet:
Client Side:
private void btnUploadFile_Click(object sender, EventArgs e)
{
string pathServer = #"C:\Users\....\Desktop\Test.pdf";
RestClient newClient = new RestClient("http://localhost:...../Service1.svc/DisplayRawData");
var request = new RestRequest(Method.GET);
request.RequestFormat = DataFormat.Json;
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
IRestResponse<TempString> newResponse = newClient.Execute<TempString>(request);
//List<TempString> rtrn = (List<TempString>)newResponse.Data;
var responseData = newClient.DownloadData(request);
FileStream fStream = new FileStream(pathServer, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fStream);
bw.Write(responseData);
bw.Close();
foreach (var xbyte in responseData)
{
// fStream.WriteByte(xbyte);
}
//fStream.Flush();
fStream.Close();
Server Side (Service)
public string DisplayRawData()
{
string path = #"C:\basketball.pdf";
byte[] fileToSend = File.ReadAllBytes(path);
string filetoSendB64 = Convert.ToBase64String(fileToSend);
// WebOperationContext.Current.OutgoingResponse.ContentType = "application/pdf";
return filetoSendB64;
}
Interface
//Getting Stream from a File
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "DisplayRawData",
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
// string DisplayRawData();
string DisplayRawData();

The code is a bit confusing, but I would say it looks like you need to decode the response string from Base64 back to a byte array before writing it to a file.

Related

How to test wcf service method that takes input as stream from REST client tool

I am creating wcf service that accepts stream as a input parameter.
Here is my method in Contract
[OperationContract(Name = "PostSampleMethod")]
[WebInvoke(Method = "POST",
UriTemplate = "PostSampleMethod")]
string PostSampleMethod(Stream data);
And here is the implementation of it
public string PostSampleMethod(Stream data)
{
// convert Stream Data to StreamReader
StreamReader reader = new StreamReader(data);
// Read StreamReader data as string
string xmlString = reader.ReadToEnd();
string returnValue = xmlString;
// return the XMLString data
return returnValue;
}
I am using ARC or Boomerang tool to test my service's method. My problem is what input data or in what format I need to send from REST client tool to test this method.
Any help is much appreciated.
Since you read the incoming stream as string(by using StreamReader), you can send any string(xml, json, free format) to your server.
var client = new HttpClient();
var content = new StringContent("aaaa");
var resp = await client.PostAsync("http://....../PostSampleMethod", content);
var status = resp.StatusCode;
var retValue = await resp.Content.ReadAsStringAsync();

Sending an Image as a Byte Array to a REST Service

I am working on a REST service which will be used to manipulate an image for example, change brightness or contrast. I currently have a Windows Form App to which I upload an image to before I send it to the Rest.
Here is the code I have so far on the Rest to receive the byte:
IRestServiceImpl.cs
[OperationContract]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "json/{id}")]
string jsonData(byte[] id);
RestServiceImpl.svc.cs
public string jsonData(byte[] id) {
return "The byte array is" + id;
}
This is my attempt to send it from the form but it just returns blank in Visual Studio's console.
private async void btnRestSend_Click(object sender, EventArgs e) {
byte[] byteArray = ImageManipulation.ImgToByte(pictureBox1.Image);
ByteArrayContent byteContent = new ByteArrayContent(byteArray);
var url = "http://localhost:52278/RestServiceImpl.svc/json/";
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(new Uri(url), byteContent);
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
ImgToByte
public static byte[] ImgToByte(Image img) {
//Converts an Image to a Byte
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(img, typeof(byte[]));
}
How do I get the byte array to be successfully sent to the rest service so I can manipulate it in there?
Thanks in advance :)
You can convert the byte array to a base 64 string in order to send it to front-end as a string or inside a JSON object.
string base64Image = Convert.ToBase64String(byteArray);
*Convert belongs to System library

Create HttpWebRequest Post request

I have a WCF POST Method - it looks like below:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "UploadReport/{customerId}/{author}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string UploadReport(string customerId, byte[] fileData, string author);
It is used to upload a Report to an ECM Client I am using.
I was calling this with a WCF Client in another solution by adding the Service reference to the WSDL. So as below:
using (MemoryStream mem = new MemoryStream())
{
ExcelReportGenerator excel = new ExcelReportGenerator();
success = excel.CreateExcelDoc(mem, customerId);
mem.Position = 0;
try
{
using (CustomerClient.UploadClient customerClient = new CustomerClient.UploadClient())
{
customerClient.Endpoint.Binding.SendTimeout = new TimeSpan(0, 10, 0);
uploadReportId = customerClient .UploadReport(customerId.ToString(), mem.ToArray(), userId.ToString());
}
//remaining code removed from brevity
However now I need to make this call from a HttpWebRequest rather than using the generated wcf client.
However, I am wondering how to do this in order to POST the byte array as well as the customer id and author.
I have used something like the below for a simple API GetRequest before
string jsonResponse = string.Empty;
string requestUri = string.Format("{0}", myAPI);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
request.Credentials = new NetworkCredential(userNameWs, passwordWs);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
jsonResponse = reader.ReadToEnd();
reader.Close();
dataStream.Close();
}
IN the above myAPI was loaded from config and looked like below:
http://localhost/myWS/api/Reference/GetAllCarManufacturers
I know to make it hit my WCF Method I would need
request.Method = "POST";
What would I need in order to POST the fileData and hit the Post URL which in the WCF is in the format "UploadReport/{customerId}/{author}

How to convert chunck by chunck byte array into base64 string?

We are reading byte array of a file and converting it into base64 string as follows
public static string ZipToBase64()
{
FileUpload fileCONTENT = FindControl("FileUploadControl") as FileUpload;
byte[] byteArr = fileCONTENT.FileBytes;
return Convert.ToBase64String(byteArr);
}
string attachmentBytes = ZipToBase64();
string json1 = "{ \"fileName\": \"Ch01.pdf\", \"data\": " + "\"" + attachmentBytes + "\"}";
When we try to convert large file upto 1 GB into base64 string, it is throwing out of memory exception. We are sending this json to restful wcf service. Following is my method in RESTful WCF Service.
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public void UploadFile1(Stream input)
{
string UserName = HttpContext.Current.Request.Headers["UserName"];
string Password = Sql.ToString(HttpContext.Current.Request.Headers["Password"]);
string sDevideID = Sql.ToString(HttpContext.Current.Request.Headers["DeviceID"]);
string Version = string.Empty;
if (validateUser(UserName, Password, Version, sDevideID) == Guid.Empty)
{
SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "Invalid username or password for " + UserName);
throw (new Exception("Invalid username or password for " + UserName));
}
string sRequest = String.Empty;
using (StreamReader stmRequest = new StreamReader(input, System.Text.Encoding.UTF8))
{
sRequest = stmRequest.ReadToEnd();
}
// http://weblogs.asp.net/hajan/archive/2010/07/23/javascriptserializer-dictionary-to-json-serialization-and-deserialization.aspx
JavaScriptSerializer json = new JavaScriptSerializer();
// 12/12/2014 Paul. No reason to limit the Json result.
json.MaxJsonLength = int.MaxValue;
Dictionary<string, string> dict = json.Deserialize<Dictionary<string, string>>(sRequest);
string base64String = dict["data"];
string fileName = dict["fileName"];
byte[] fileBytes = Convert.FromBase64String(base64String);
Stream stream = new MemoryStream(fileBytes);
//FileStream fs1 = stream as FileStream;
string networkPath = WebConfigurationManager.AppSettings["NetWorkPath"];
File.WriteAllBytes(networkPath + "/" + fileName, fileBytes); // Requires System.IO
}
Please provide solution for converting large byte array into base64 string
The fact you use Stream input in your wcf service does not really mean you pass anything in streamed manner. In fact in your case you do not, because:
You buffer whole file on client in memory to build json string.
You buffer whole file on server in memory via stmRequest.ReadToEnd().
So no streaming takes place. First you should realize that no json is needed here - you just need to pass file in your http request body. What you should do first is throw away all code below security checks in your UploadFile1 method and instead do this:
public void UploadFile1(string fileName, Stream input) {
// check your security headers here
string networkPath = WebConfigurationManager.AppSettings["NetWorkPath"];
using (var fs = File.Create(networkPath + "/" + fileName)) {
input.CopyTo(fs);
}
}
Here we just copy input stream to output stream (file) without any buffering (of course CopyTo will buffer chunks but they will be very small). Mark your service method with:
[WebInvoke(Method = "POST", UriTemplate = "/UploadFile1/{fileName}")]
To allow you pass filename in query string.
Now to client. Not sure which method you use to communicate with server, I'll show example with raw HttpWebRequest.
var filePath = "path to your zip file here";
var file = new FileInfo(filePath);
// pass file name in query string
var request = (HttpWebRequest)WebRequest.Create("http://YourServiceUrl/UploadFile1/" + file.Name);
request.Method = "POST";
// set content length
request.ContentLength = file.Length;
// stream file to server
using (var fs = File.OpenRead(file.FullName)) {
using (var body = request.GetRequestStream()) {
fs.CopyTo(body);
}
}
// ensure no errors
request.GetResponse().Dispose();

get image from web service and show on Winforms

i m developing a C# Window Application which uses web service as it's back end,
how to get image from specified URL:
the image on server is in JPEG Format
var client = new RestClient();
client.BaseUrl = "http://www.*****.com/images/12345.jpg";
var request = new RestRequest();
IRestResponse response = client.Execute(request);
Using RestSharp I did it this Way
var client = new RestClient();
client.BaseUrl = "http://www.abcd.com/image1.jpg";
var request = new RestRequest();
picturebox1.Image = new Bitmap(new MemoryStream(client.DownloadData(request)));
Showing Image at Picture Box
If the client has the image URL, why not just use HTTP to download it? Or are you saying that the images will always reside on the same server that the WebService is running on, and that the WebService method should accept a URL, translate it to a local path, and return the image as a byte array?
We have a method of our WSDL WebService that does about the same thing, we don't include the protocol and host portions of the URL (they'd be redundant.)
[WebMethod]
public byte[] GetPicture(string ImageURL)
{
if (ImageURL.StartsWith("http"))
return new byte[0];
string tmp = System.Web.Hosting.HostingEnvironment.MapPath("/" + ImageURL);
string FileName = Microsoft.JScript.GlobalObject.unescape(tmp);
if (System.IO.File.Exists(FileName))
{
FileStream fs = System.IO.File.OpenRead(FileName);
byte[] buf = new byte[fs.Length];
fs.Read(buf, 0, (int)fs.Length);
fs.Close();
return buf;
}
else
return new byte[0];
}
Does that answer your question?

Categories