I'm using Refit in my C# application to interact with a REST API, and the API method has a call that returns a .jpg image. I want to download this image using Refit and get it as a byte array, but it seems to return a garbled string. See below. See below interface method for downloading of the image
[Get("/Photos/{id}")]
Task<string> DownloadPhoto(Guid id);
I tried parsing the string as a Base64 string but that didn't work, so I presume it's not that. Any ideas?
EDIT: First line of garbled response here. Note if going to this same URL in a browser it works fine and displays the image
����\0\u0010JFIF\0\u0001\u0001\0\0H\0H\0\0��\0XExif\0\0MM\0*\0\0\0\b\0\u0002\u0001\u0012\0\u0003\0\0\0\u0001\0\u0001\0\0�i\0\u0004\0\0\0\u0001\0\0\0&\0\0\0\0\0\u0003�\u0001\0\u0003\0\0\0\u0001\0\u0001\0\0�\u0002\0\u0004\0\0\0\u0001\0\0\u0002X�\u0003\0\u0004\0\0\0\u0001\0\0\u0003 \0\0\0\0��\08Photoshop 3.0\08BIM\u0004\u0004\0\0\0\0\0\08BIM\u0004%\0\0\0\0\0\u0010�\u001d�ُ\0�\u0004�\t���B~��\0\u0011\b\u0003 \u0002X\u0003\u0001\"\0\u0002\u0011\u0001\u0003\u0011\u0001��\0\u001f
What worked for me was to have the method declared as returning
Task<HttpContent> and then you can retrieve the data from the returned HttpContent instance in a variety of manners.
For example:
Task<HttpContent> DownloadPhoto(Guid id);
And then:
HttpContent content = await DownloadPhoto(guid);
byte[] bytes = await content.ReadAsByteArrayAsync();
you can get the byte array using refit as in the example below
[Get("/Photos/{id}")]
Task<HttpResponseMessage> DownloadPhoto(Guid id);
and then you can get the byte array from
var Response = await YourRefitClient.DownloadPhoto(id);
byte[] ByteArray = await Response.Content.ReadAsByteArrayAsync();
Related
I'm building an ASP.NET Core Web API in C#. I receive a PDF file in the request body.
When I write the bytes of the request body, I get a file having base64 string (which should be decoded to get the actual PDF).
I don't know what to do next .. please advise ..
var ms = new MemoryStream((int)Request.ContentLength);
req.CopyToAsync(ms).GetAwaiter().GetResult();
System.IO.File.WriteAllBytes("test.pdf", ms.ToArray());
When I open test.pdf, I get something like the below:
JVBERi0xLjUNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBl............cnR4cmVmDQoxODkzOQ0KJSVFT0Y=
Get the raw body using ReadAsStringAsync, then use Convert.FromBase64String() to convert it to bytes.
string base64 = await request.Content.ReadAsStringAsync();
byte[] bytes = Convert.FromBase64String(base64);
System.IO.File.WriteAllBytes("test.pdf", bytes);
I have a simple GET request that returns .txt file's content. You can try it out using a browser or fiddler: http://134.17.24.10:8054/Documents/13f37b0c-4b04-42e1-a86b-3658a67770da/1.txt
The encoding of this file is cp-1251. When I try to get it, I see smth like this:
response text view
How can I modify HttpRequest in C# to get the text in the encoding that I want? Or just return only bytes in order to convert them manually. Is it possible with HttpClient?
Another attachment:
If you can't change the charset sent by the server, yes, you can still just request the bytes and then choose which encoding to apply:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetByteArrayAsync(RequestUrl);
var responseString = Encoding.GetEncoding("windows-1251").GetString(response, 0, response.Length - 1);
Console.WriteLine(responseString);
}
References:
How to change the encoding of the HttpClient response
Encoding.GetEncoding can't work in UWP app
The .NET Framework Class Library provides one static property, CodePagesEncodingProvider.Instance, that returns an EncodingProvider object that makes the full set of encodings available on the desktop .NET Framework Class Library available to .NET Core applications.
https://learn.microsoft.com/en-us/dotnet/api/system.text.encodingprovider?redirectedfrom=MSDN&view=netcore-3.1
I am making a Web Api and I need to return multiple images to the client. I am currently using a Base64 string for each image but this results in each request taking far too long. Is there a better, more efficient way of returning images?
This is the code I am using:
Controller:
public LearningUnits GetLearningUnits([FromODataUri]Guid key)
{
var record = db.LearningUnits.SingleOrDefault(inst => inst.LearningUnitId == key);
record.ImageURLPath = ImageHandler.ImageToByteArrayFromFilePath(record.ImageURLPath);
return record;
}
ImageToByteArray Method:
public static string ImageToByteArrayFromFilePath(string imagefilePath)
{
byte[] imageArray = File.ReadAllBytes(imagefilePath);
string baseImage = Convert.ToBase64String(imageArray);
return baseImage;
}
If the endpoint returns json, then there is no other way, beyond base64, how to embed binaries within the response. But it is definitely a bad idea due to the performance issues. May be for some icons it would be ok, but for larger images its not suitable.
So the best solution here, is to return the url to the image. And the client will make further request to get raw bytes for the image.
Also worth to mention, the image url can not only be the path to the static file, but also a path to some webapi endpoint, which, for instance, gets the image bytes by the resource id and sends the client raw binary back, and not a json string.
The solution is to use media formatters, so that when the Web API is queried with a particular type, you'll then receive the actual binary stream of the particular type.
http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters
This is the standard RESTful pattern; you have the same URL, but when you want a JSON record for the data, you accept-type:application/json, but you change your MIME request type to image/png or something similar when you want that media type.
More can be found here:
How to provide custom mediatype formats for OData Api
Odata also implicitly supports it here: https://msdn.microsoft.com/en-us/library/system.web.http.odata.formatter.odatamediatypeformatter(v=vs.118).aspx
I am adding features to a Windows Phone 8.1 RT app, built using MVVM. I need to be able to download an Image to the device and save/ display it. I can already do this with images from a fixed URL.
We have an accompanying website and API to go with the app. The way it works is the app sends a request to the API to get a download code for the image in question, and then sends this code along with the ID of the document in a request to the website, which verifies the user has access to the document and should then serve up the image if successful. The API and website are already in use with the iOS and Android equivalents of the app, so I know they work.
To retrieve the image, I'm trying to use HttpClient. This is my current code, which is getting a response from the server, with some content and the filename of the image (which look to be correct):
Uri uri = new Uri("<website address>");
Dictionary<string, string> pairs = new Dictionary<string, string>();
pairs.Add("RequestToken", response.DownloadToken);
pairs.Add("DocumentID", "<doc ID>");
HttpFormUrlEncodedContent formContent = new HttpFormUrlEncodedContent(pairs);
HttpClient client = new HttpClient();
HttpResponseMessage response2 = await client.PostAsync(uri, formContent);
var imageContent = response2.Content.ReadAsInputStreamAsync();
I'm trying to write the content to a stream, then convert that to a BitmapImage object, which I can then save to the device and display to the user. It's the conversion I'm struggling with. My plan is to convert the InputStream to a bytearray, then convert that to a Bitmap. The problem is, I can't find any extension methods in 8.1 which will do this, and very little in the way of documentation to help.
Can anyone point me in the right direction here? Maybe there's a better way of doing a conversion from HttpResponseMessage.Content to BitmapImage?
Make sure you are importing the right HttpClient:
using Windows.Web.Http;
And import other necessary namespaces:
using Windows.Storage.Streams;
using Windows.UI.Xaml.Media.Imaging;
Then, as you wrote in your qurestion, get the IInputStream, but make sure to use await with ReadAsInputStreamAsync():
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(uri, formContent);
// Do not forget to use an 'await'.
IInputStream imageStream = await response.Content.ReadAsInputStreamAsync();
Then, copy the IInputStream into an IRandomAccessStream:
InMemoryRandomAccessStream randomAccessStream =
new InMemoryRandomAccessStream();
await RandomAccessStream.CopyAsync(imageStream, randomAccessStream);
This is important, rewind the IRandomAccessStream:
// Rewind.
randomAccessStream.Seek(0);
Finally, create a BitmapImage and assign it to your XAML Image control:
var bitmap = new BitmapImage();
bitmap.SetSource(randomAccessStream);
MyImage.Source = bitmap;
That's all!
If you need a URI to test, try this one:
Uri uri = new Uri("http://heyhttp.org/emoji.png");
HttpResponseMessage response = await client.GetAsync(uri);
I'm sure it's a common question, and I probably find solutions to this but I didn't understand them. Besides I'm doing this completely blind. Another point is: I don't want to use third party libraries.
I need to send an image from my Android app to my server via c# rest webservice.
I watched this method to convert the bitmap to a byte[].
public static byte[] getBitmapAsByteArray(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 0, outputStream);
return outputStream.toByteArray();
}
And here I have two (at least) problems:
How to send it as JSON? I tried Base64.encode() with COMMON and URLSAFE (or something like that) flags and I get error at server side: Not a valid Base64.
Then I suppose the client side it's ok, so how do I manage to receive and process the byte[]? Now it seems it try to convert automatically and it fails, maybe because client sends invalid data or well... I don't know.
I can't provide code right now (in fact I think I don't have code to do this at all), but I'll update with what I have if required.
Thanks and sorry for this horrible made question
Android :
byte[] content = getBitmapAsByteArray(bitmap);
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new ByteArrayEntity(content));
HttpResponse response = httpClient.execute(httpPost);
c#.net
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}