Если вы пропустили предыдущие четыре части, вы можете легко найти их здесь:
- Создание клиента 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!