Если вы пропустили предыдущие четыре части, вы можете легко найти их здесь:
- Создание клиента Imgur для Windows Phone — часть 1 — Core & Main Gallery
- Создание клиента Imgur для Windows Phone — часть 2 — бесконечная прокрутка изображений
- Создание клиента Imgur для Windows Phone — часть 3 — просмотр сведений об изображении
- Создание клиента Imgur для Windows Phone — Часть 4 — Аутентификация
Вероятно, самая интересная часть о клиенте Imgur, который мы создаем, — это его способность загружать изображения наряду с возможностью визуализировать основной ассортимент галереи. Существует специальная конечная точка, которая была разработана для выполнения этой задачи —
/ image .
Прежде чем углубляться в механизм загрузки, давайте вспомним, как пользователь может выбрать изображение на устройстве Windows Phone. Чтобы читать фотографии с устройства, вам нужно использовать PhotoChoserTask . Более того, это также позволит пользователю сделать новый снимок, если это необходимо.
В моем приложении я просто добавил кнопку «Загрузить» и использовал следующий фрагмент для преобразования возвращенного изображения в двоичное содержимое:
PhotoChooserTask task = new PhotoChooserTask() { ShowCamera = true }; task.Completed += (s,d) => { if (d.TaskResult == TaskResult.OK) { byte[] buffer = new byte[16*1024]; using (MemoryStream stream = new MemoryStream()) { int read = 0; while ((read = d.ChosenPhoto.Read(buffer, 0, buffer.Length)) > 0) { stream.Write(buffer, 0, read); } App.ServiceClient.UploadImage(stream.ToArray(), "WP Imagine Test", "Test"); } } }; task.Show();
Это передаст массив, созданный из потока изображений, в функцию UploadImage, которая является моей реализацией механизма загрузки. Посмотрите на это:
public void UploadImage(byte[] content, string title, string description, Action<bool> onCompletion = null) { string BOUNDARY = Guid.NewGuid().ToString(); string HEADER = string.Format("--{0}", BOUNDARY); string FOOTER = string.Format("--{0}--", BOUNDARY); HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.imgur.com/3/upload"); request.Method = "POST"; request.Headers["Authorization"] = "Client-ID " + _clientID; request.ContentType = "multipart/form-data, boundary=" + BOUNDARY; StringBuilder builder = new StringBuilder(); string base64string = Convert.ToBase64String(content); builder.AppendLine(HEADER); builder.AppendLine("Content-Disposition: form-data; name=\"image\""); builder.AppendLine(); builder.AppendLine(base64string); builder.AppendLine(FOOTER); byte[] bData = Encoding.UTF8.GetBytes(builder.ToString()); request.BeginGetRequestStream((result) => { using (Stream s = request.EndGetRequestStream(result)) { s.Write(bData, 0, bData.Length); } request.BeginGetResponse((respResult) => { try { HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(respResult); using (StreamReader reader = new StreamReader(response.GetResponseStream())) { Debug.WriteLine(reader.ReadToEnd()); } } catch (WebException ex) { using (StreamReader reader = new StreamReader(ex.Response.GetResponseStream())) { Debug.WriteLine(reader.ReadToEnd()); } } }, null); }, null); }
Это может показаться довольно длинным, но на самом деле он выполняет довольно простую задачу — создает POST-запрос multipart / form-data . Обратите внимание, что в отличие от обычного подхода представление содержимого изображения в base64 не исключается — при создании многочастного POST-запроса экранирование строки приведет к сбою вызова API, поэтому убедитесь, что вы этого не делаете. Кроме того, вам все равно нужно будет передать свой идентификатор клиента, даже если вы можете загрузить изображение анонимно (без привязки к определенной учетной записи пользователя).
Способ, которым этот метод работает в настоящее время, будет загружать только изображение без метаданных, связанных с ним, таких как заголовок и описание для него. Давайте исправим это и добавим условные выражения, которые бы проверяли, должны ли заголовок и описание быть прикреплены к запросу.
if (!string.IsNullOrWhiteSpace(title)) { builder.AppendLine(HEADER); builder.AppendLine("Content-Disposition: form-data; name=\"title\""); builder.AppendLine(); builder.AppendLine(title); } if (!string.IsNullOrWhiteSpace(description)) { builder.AppendLine(HEADER); builder.AppendLine("Content-Disposition: form-data; name=\"description\""); builder.AppendLine(); builder.AppendLine(description); }
Еще раз, мы следуем стандартным требованиям multipart / form-data для добавления дополнительных параметров. Как только изображение будет загружено, вы сможете увидеть заголовок и описание на странице изображения:
Если загрузка прошла успешно, мы можем ожидать получения следующей информации:
- ID изображения
- Удалить хеш
- Полный URL изображения
Их можно легко десериализовать, поэтому я легко могу использовать существующую
модель Image , просто добавив
свойство DeleteHash и связав его с
полем deletehash в возвращаемой строке JSON.
public class ImgurImage { public string ID { get; set; } [JsonProperty(PropertyName="deletehash")] public string DeleteHash { get; set; } public string Title { get; set; } public Int64 DateTime { get; set; } public string Type { get; set; } [JsonProperty(PropertyName = "animated")] public bool IsAnimated { get; set; } public int Width { get; set; } public int Height { get; set; } public Int64 Size { get; set; } public Int64 Views { get; set; } [JsonProperty(PropertyName = "account_url")] public string AccountUrl { get; set; } public string Link { get; set; } public string Bandwidth { get; set; } public int Ups { get; set; } public int Downs { get; set; } public int Score { get; set; } [JsonProperty(PropertyName = "is_album")] public bool IsAlbum { get; set; } }
Когда изображение возвращается, мы больше не имеем дело с массивом изображений, поэтому модель ImgurImageData может быть не такой подходящей. Вместо этого я создал класс ImgurAtomicImageData :
using Newtonsoft.Json; namespace Imagine.ImgurAPI { class ImgurAtomicImageData { [JsonProperty(PropertyName = "data")] public ImgurImage Image { get; set; } public bool Success { get; set; } public int Status { get; set; } } }
Когда ответ получен, я могу использовать общий DeserializeObject для ImgurAtomicImageData :
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(respResult); using (StreamReader reader = new StreamReader(response.GetResponseStream())) { string jsonContent = reader.ReadToEnd(); var imageData = JsonConvert.DeserializeObject<ImgurAtomicImageData>(jsonContent); Debug.WriteLine(jsonContent); }
В результате вы сможете получить как HTTP-код, так и базовую модель изображения, содержащую все три поля данных, которые я упоминал выше.
Поздравляем, теперь вы можете загружать изображения в Imgur со своего Windows Phone!