Sending an Image as a Byte Array to a REST Service - c#

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

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();

How to Send and receive excel data using web service

How to Send and receive excel data using web service
I have created a web application to send excel file data to a web service.
protected void Page_Load(object sender, EventArgs e)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:58959/RESTServiceImpl.svc/PostFile");
request.ContentType = "application/vnd.ms-excel";
request.Headers.Add("filename", "fooBar.xls");
request.Method = WebRequestMethods.Http.Post;
byte[] fileData = System.IO.File.ReadAllBytes("C:\\Users\\Public\\Documents\\Forecast Pro TRAC\\Input\\Book1.xls");
request.ContentLength = fileData.Length;
using (System.IO.BinaryWriter postStream = new System.IO.BinaryWriter(request.GetRequestStream()))
{
postStream.Write(fileData);
postStream.Flush();
postStream.Close();
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
System.Diagnostics.Debug.Assert(response.StatusCode == HttpStatusCode.OK);
string responseMessage = string.Empty;
using (System.IO.StreamReader sr = new System.IO.StreamReader(response.GetResponseStream()))
{
responseMessage = sr.ReadToEnd();
}
System.Diagnostics.Debug.WriteLine(responseMessage);
}
Now I need to receive that excel data from WCF application. So I have done something like below code. I am getting total bytes that I am sending. What are exact things I need to do in both end to send and receive excel data.
[ServiceContract]
public interface IRESTServiceImpl
{
[OperationContract]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "PostFile")]
string PostFile();
}
public class RESTServiceImpl : IRESTServiceImpl
{
public string PostFile()
{
var httpRequest = HttpContext.Current.Request;
var bites = httpRequest.TotalBytes;
return httpRequest.FilePath;
}
}
I am very new in web service and this is my first application. So please please help me.
Thanks in advance.
I have solved the solution and here is the working code
public class RestServiceImpl : IRestServiceImpl
{
public string PostFileRest(Stream fileContents)
{
var httpRequest = HttpContext.Current.Request;
var filePath = "C:\\file.xls"; //excel filePath for local
var bites = httpRequest.TotalBytes;
//Convert stream to byte array
byte[] reqBytes = readRequest(fileContents, bites);
byte[] decodedReqBytes = HttpUtility.UrlDecodeToBytes(reqBytes);
string json = System.Text.Encoding.UTF8.GetString(reqBytes);
DataTable dt = JsonConvert.DeserializeObject<DataTable>(json);
MemoryStream stream = new MemoryStream(reqBytes);
FileStream file = new FileStream(filePath, FileMode.Create, FileAccess.Write);
stream.WriteTo(file);
file.Close();
stream.Close();
return json ;
}
#region Convert Stream to byte array
private byte[] readRequest(Stream fileContents, int bites)
{
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
int BUFFER_SIZE = bites;
int iRead = 0;
int idx = 0;
Int64 iSize = 0;
memStream.SetLength(BUFFER_SIZE);
while (true)
{
byte[] reqBuffer = new byte[BUFFER_SIZE];
try
{
iRead = fileContents.Read(reqBuffer, 0, BUFFER_SIZE);
}
catch (System.Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
if (iRead == 0)
{
break;
}
iSize += iRead;
memStream.SetLength(iSize);
memStream.Write(reqBuffer, 0, iRead);
idx += iRead;
}
byte[] content = memStream.ToArray();
memStream.Close();
return content;
}
#endregion
}
The Interface-
[ServiceContract]
public interface IRestServiceImpl
{
[OperationContract]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "PostFileRest")]
string PostFileRest(Stream fileContents);
}

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();

How to get PDF back from a byte array

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.

REST Service receive empty params

I'm trying to comunicate with my rest service but this one return always that my sended parameter is empty but in my client console he is filled.
Here is the Interface Class :
[ServiceContract]
public interface IMyTest
{
[OperationContract]
[WebInvoke(UriTemplate = "TestMe", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped)]
string TestMe(string parameter);
}
My svc method :
public string TestMe(string parameter)
{
if (string.IsNullOrEmpty(parameter)
return "Empty";
return "OK";
}
My client :
string content = "{\"Param\" : \"TEST\"}";
var request = WebRequest.Create("http://localhost/MyTestURL/MyTest.svc/TestMe");
request.Method = "POST";
request.ContentType = "application/json";
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(content);
}
var res = (WebResponse)request.GetResponse();
StreamReader reader =
new StreamReader(res.GetResponseStream(), Encoding.UTF8);
System.Console.WriteLine("Response");
System.Console.WriteLine(reader.ReadToEnd().ToString());
Is my client code not ok ? My conifiguration not ok ? ...
Thanks.
If you want to get request as string, use Stream instead of String parameter
public void TestMe(Stream dataStream)
but if not, use serializable to Json objects as parameters.
i founded a good tutorial that helped me to implement the method with the stream parameter. thanks.

Categories