I'm making a call to an API that consists in a HTTP Post request. The data i want to post is an image, properly converted into a byte array.
The response is not as expected, and i want to know what is the error: is it my code or is it the API? This is the code that i'm using
Image i = new Image();
BitmapImage bi = new BitmapImage(new Uri("/Images/dmoc.jpeg", UriKind.Relative));
testImage.Source = bi;
byte[] rawimage = ImageConverter.ImageToBytes(bi);
try
{
var baseAddress = new Uri("http://private-anon-6cf48a749-yugiohprices.apiary-mock.com/");
using (var httpClient = new HttpClient { BaseAddress = baseAddress })
{
//HttpRequestHeader.ContentType
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("image/jpeg"));
using (var response = await httpClient.PostAsync("api/match_card_image", new ByteArrayContent(rawimage)))
{
string responseData = await response.Content.ReadAsStringAsync();
postTxt.Text = responseData;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
MessageBox.Show(ex.StackTrace);
}
where ImageConverter is my class.
Related
I am getting error width cannot be null , when passing image to inputstream.As i didn't find any alterante method . Basically i want to convert image to Pdf format in Xamarin.forms which supports UWP platform .
I am using xfinium pdf library for this.
public void ConvertJpegToPdf()
{
try
{
PdfFixedDocument document = new PdfFixedDocument();
Xfinium.Pdf.PdfPage page = document.Pages.Add();
page.Width = 800;
page.Height = 600;
var imageStream = GetStream();
PdfJpegImage jpeg = new PdfJpegImage(imageStream);//<-Error
PdfStandardFont helvetica = new PdfStandardFont(PdfStandardFontFace.Helvetica, 24);
PdfBrush brush = new PdfBrush(PdfRgbColor.Red);
page.Graphics.DrawImage(jpeg, 0, 0, page.Width, page.Height);
Stream pdfStream = null;
document.Save(pdfStream);
}
catch (Exception ex)
{
throw ex;
}
}
protected Stream GetStream()
{
byte[] byteArray = Encoding.UTF8.GetBytes("http://david.qservicesit.com/images/3.jpg");
MemoryStream stream = new MemoryStream(byteArray);
return stream;
}
Please suggest some alternate to do this
byte[] byteArray = Encoding.UTF8.GetBytes("http://david.qservicesit.com/images/3.jpg");
You could not get image stream in this way. The method you have used can only get the Bytes of string. For your scenario, you could use http client to acquire image stream. Please refer to the following code:
public async Task<Stream> GetStream()
{
HttpClient client = new HttpClient();
HttpResponseMessage res = await client.GetAsync(new Uri("http://david.qservicesit.com/images/3.jpg"));
Stream stream = await res.Content.ReadAsStreamAsync();
return stream;
}
public async Task ConvertJpegToPdf()
{
try
{
PdfFixedDocument document = new PdfFixedDocument();
Xfinium.Pdf.PdfPage page = document.Pages.Add();
page.Width = 800;
page.Height = 600;
var imageStream = await GetStream();
PdfJpegImage jpeg = new PdfJpegImage(imageStream);
PdfStandardFont helvetica = new PdfStandardFont(PdfStandardFontFace.Helvetica, 24);
PdfBrush brush = new PdfBrush(PdfRgbColor.Red);
page.Graphics.DrawImage(jpeg, 0, 0, page.Width, page.Height);
Stream pdfStream = new MemoryStream();
document.Save(pdfStream);
}
catch (Exception ex)
{
throw ex;
}
}
Call Rest service
Rest service returns byte[] representation of image/audio/video
convert into byte[] to image and show in content page in xamarin
First of all, you can create a function that simply makes an API request and obtains the content in the form of byte array. A simple example of HTTP request:
public static byte[] GetImageByteArray(string url)
{
try
{
using (var client = new HttpClient())
{
var uri = new Uri(url);
var response = client.GetAsync(uri).Result;
if (response.IsSuccessStatusCode)
{
var content = response.Content.ReadAsByteArrayAsync();
return content.Result;
}
}
return null;
}
catch
{
return null;
}
}
Next, you can simply bind the output from your result into your image source and the image to your content:
var mainStack = new StackLayout();
var imageByteArray = GetImageByteArray("https://static.pexels.com/photos/34950/pexels-photo.jpg");
Image image;
if (imageByteArray != null)
{
image = new Image()
{
Source = ImageSource.FromStream(() => new MemoryStream(imageByteArray))
};
mainStack.Children.Add(image);
}
Content = mainStack;
Since I am new to Xamarin, I would really appreciate if someone could explain me how to consume RESTful service (returning JSON data) using Xamarin Forms with the simplest example.
You can use JSON.net and HTTP request, here is a quick example of how to use the movie database which is a free movie database GET and POST examples, hope this helps:
const string _baseUrl = "http://api.themoviedb.org/3/";
const string _pageString = "&page=";
//GET Example
public static async Task<ObservableCollection<Movie>> GetTopRatedMoviesAsync(int page = 1)
{
HttpClient client = new HttpClient();
//_apiKey = themoviedb api key, page = page size 1 = first 20 movies;
string topRatedUrl = _baseUrl + "movie/top_rated?" + _apiKey + _pageString + page;
HttpResponseMessage result = await client.GetAsync (topRatedUrl, CancellationToken.None);
if (result.IsSuccessStatusCode) {
try{
string content = await result.Content.ReadAsStringAsync ();
ObservableCollection<Movie> MovieList = GetJsonData(content);
//return a ObservableCollection to fill a list of top rated movies
return MovieList;
}catch(Exception ex){
//Model Error
Console.WriteLine (ex);
return null;
}
}
//Server Error or no internet connection.
return null;
}
static ObservableCollection<Movie> GetJsonData(string content){
JObject jresponse = JObject.Parse (content);
var jarray = jresponse ["results"];
ObservableCollection<Movie> movieList = new ObservableCollection<Movie> ();
foreach (var jObj in jarray) {
Movie newMovie = new Movie();
newMovie.Title = (string)jObj["title"];
newMovie.PosterPath = _baseImgUrl + (string)jObj["poster_path"];
newMovie.HighResPosterPath = _baseImgUrl + (string)jObj["poster_path"];
newMovie.Id = (int)jObj["id"];
newMovie.Overview = (string)jObj["overview"];
newMovie.VoteCount = (double)jObj["vote_count"];
newMovie.ReleaseDate = (DateTime)jObj["release_date"];
newMovie.VoteAverage = (float)jObj["vote_average"];
movieList.Add(newMovie);
}
return movieList;
}
//POST Example:
public static async Task<bool> PostFavoriteMovieAsync(Movie movie)
{
try
{
HttpClient client = new HttpClient();
//_sessionId = string with the movie database session.
string tokenUrl = _baseUrl + "account/id/favorite?" + _apiKey + _sessionId;
string postBody = JsonConvert.SerializeObject(new Favorite{
favorite = !movie.Favorite,
media_id = movie.Id,
});
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.PostAsync (tokenUrl,
new StringContent (postBody, Encoding.UTF8, "application/json"));
if(response.IsSuccessStatusCode)
return true;
else
return false;
}
catch(Exception ex){
Console.WriteLine (ex.Message);
return false;
}
}
I need to load a picture from a web api backend into my Xamarin.Forms app.
The picture is stored in an Azure Blob Storage.
This is my Web Api method:
[HttpGet("{id}")]
public HttpResponseMessage Get(int id)
{
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("ConnectionString");
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("picturecontainer");
// Retrieve reference to a blob named "photo.jpg".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("picture");
var stream = new MemoryStream();
blockBlob.DownloadToStream(stream);
Image image = Image.FromStream(stream);
MemoryStream memoryStream = new MemoryStream();
image.Save(memoryStream, ImageFormat.Jpeg);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(memoryStream.ToArray());
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
return result;
}
In my app I try to download the image bytes with the following code:
public App ()
{
_client = new HttpClient();
_client.MaxResponseContentBufferSize = 256000;
Button downloadImageBtn = new Button () {
Text = "Download Image",
};
var image = new Image() {
Source = ImageSource.FromUri (new Uri ("http://www.engraversnetwork.com/files/placeholder.jpg")),
Aspect = Aspect.AspectFit
};
downloadImageBtn.Clicked += async (object sender, EventArgs e) => {
var values = await handleClick (sender, e);
uploadPicButton.Text = values;
var imageBytes = await downloadPicture();
image.Source = ImageSource.FromStream(() => new MemoryStream(imageBytes));
};
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
image,
downloadImageBtn
}
}
};
}
private async Task<byte[]> downloadPicture()
{
var uri = new Uri (string.Format (RestUrl, "5"));
//return await _client.GetByteArrayAsync (uri);
var response = await _client.GetAsync (uri);
if (response.IsSuccessStatusCode) {
var content = await response.Content.ReadAsByteArrayAsync ();
return content;
}
throw new HttpRequestException ();
}
However when I click on the button, the placeholder image disappears.
Is there a problem when sending the image from the server or when receiving it in the app?
I'd not implement downloading Images manually.
If you want to load more images and/or allow to display a placeholder while loading, I recommend the FFImageLoading library. It offers nice functionality like downloading, caching, showing placeholder and error images and most important: down sampling the image to the target size. This is always a pain on android. Its available for native UI xamarin projects and for Xamarin.Froms.
You can bind strings that contain urls directly to the Source. The code would like like:
<ffimageloading:CachedImage
Source="http://thecatapi.com/?id=MTQ5MzcyNA">
</ffimageloading:CachedImage>
After blockblob.DownloadToStream line, try to set Position of the stream to 0. I'm not familiar with Azure API, but I think it may help.
Also ,try to use ReadAsStreamAsync instead of ReadAsByteArrayAsync in your downloadPicture function. Something like this:
var responseStream = await response.Content.ReadAsStreamAsync();
byte[] buf = new byte[512];
int bufSize;
while((bufSize = (await responseStream.ReadAsync(buf, 0, buf.Length))) > 0)
{
// store the received bytes to some buffer until the file is fully downloaded
}
Do you get all your content this way?
Using image handler to convert relative path to absolute.
protected byte[] ConvertHTMLToPDF(string HTMLCode)
{
if (Request.Url == null)
throw new Exception();
var doc = new Document(PageSize.A4);
doc.Open();
var interfaceProps = new Hashtable();
var ih = new ImageHander {BaseUri = Request.Url.ToString()};
interfaceProps.Add("img_provider", ih);
foreach (IElement element in HTMLWorker.ParseToList(new StringReader(HTMLCode), null, interfaceProps))
{
doc.Add(element);
}
var _xmlr = new XmlTextReader(new StringReader(HTMLCode));
HtmlParser.Parse(doc, _xmlr);
var stream = new MemoryStream();
PdfWriter.GetInstance(doc, stream);
doc.Close();
return stream.ToArray();
}
class:
public class ImageHander : IImageProvider
{
public string BaseUri;
public Image GetImage(string src, Hashtable h, ChainedProperties cprops, IDocListener doc)
{
string imgPath;
if (src.ToLower().Contains("http://") == false)
imgPath = HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + src;
else
imgPath = src;
return Image.GetInstance(imgPath);
}
}
imgPath at the end is correct. But it's not static file, it's url of action that returns image, so I need to pass cookies when requesting image. Is it possible?
Yes, it is possible, but you're gonna have to send the request yourself and not rely on the Image.GetInstance method. For example using the HttpClient you could send cookies along with the request:
var imageUrl = new Uri(imagePath);
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler))
{
cookieContainer.Add(
new Uri(imageUrl.GetLeftPart(UriPartial.Authority)),
new Cookie("CookieName", "cookie_value")
);
var response = client.GetAsync(imageUrl).Result;
response.EnsureSuccessStatusCode();
Stream imageStream = response.Content.ReadAsStreamAsync().Result;
// You've got the Stream here, read the documentation of iTextSharp
// how to create an Image instance from a Stream:
return Image.FromStream(imageStream); // ?????
// or maybe there's a method allowing you to create an Image from byte[]
byte[] imageData = new byte[imageStream.Length];
imageStream.Read(imageData, 0, imageData.Length);
return Image.FromByteArray(imageData); // ?????
}