HTTP POST изображений на PHP с Windows Phone 8

На днях, разрабатывая приложения для Windows Phone 8 я наткнулся на одну проблем, все еще актуальную при разработке клиент-серверных приложений с бэк-эндом на PHP(и не только).

На днях, разрабатывая приложения для Windows Phone 8 я наткнулся на одну проблем, все еще актуальную при разработке клиент-серверных приложений с бэк-эндом на PHP(и не только).

Проблема в общих чертах обрисовывалась так "Как отправить изображение POST запросом на PHP сервер с Windows Phone". И Stackoverflow буквально разрывается от подобных вопросов, но осмысленных или правильных(работающих по сей день я не нашел).

Но после двух дней мучений я все же нашел решение.

Занимаясь разработкой под Windows RT я очень привык к HTTPClient, который большинство дел берет на себя и тебе не приходиться много париться. Но начиная разработку под Windows Phone, понимаешь что Microsoft учли все ошибки допущенные в Windows Phone и исправили их Windows RT, что кстати прекрасно.

Но у меня получился Downgrade. И без моего любимого HTTPClient мне пришлось тяжко.

У меня на вооружении были 2 варианта работы с HTTP: первый это WebClient(предшественник HTTPClient) и HTTPWebRequest. Разница между ними в том что WebClient проще, а HTTPWebRequest дает больше возможностей и контроля. И я решил использовать второй вариант.

Начнем с создания кнопки и привязывания к ней метода:

Кнопка:

<shell:ApplicationBarIconButton IconUri="/Images/Camera.png" Text="Изменить аватар" Click="EditAvatarApp" />

Метод обработки события:

private void EditAvatarApp(object sender, EventArgs e)

{

selectphoto = new PhotoChooserTask();

selectphoto.Completed += new EventHandler<PhotoResult>(selectphoto_Completed);   selectphoto.Show();

}

Тут видно, что после того как мы выбрали изображение нужно вызывать метод:

selectphoto_Completed.(описание ниже) Что мы и делаем.

void selectphoto_Completed(object sender, PhotoResult e)

{

feed = new UploadAvatar();

if (e.TaskResult == TaskResult.OK)

{

var memoryStream = new MemoryStream();

e.ChosenPhoto.CopyTo(memoryStream);

byte[] results = memoryStream.ToArray();

WebRequest request = HttpWebRequest.Create("http://mysite.com/upload.php");

request.Method = "POST";

request.ContentType = "application/x-www-form-urlencoded";

request.BeginGetRequestStream((reqResult) =>

{

using (Stream strm = request.EndGetRequestStream(reqResult))

using (StreamWriter writer = new StreamWriter(strm))

{

writer.Write("&message=" + HttpUtility.UrlEncode("Im testing upload"));

writer.Write("&avatar=" + HttpUtility.UrlEncode(System.Convert.ToBase64String(results)));

}

request.BeginGetResponse((result) =>

{

try

{

var response = request.EndGetResponse(result);

using (var rstrm = response.GetResponseStream())

{

var serializer = new DataContractJsonSerializer(typeof(UploadAvatar));

var postResponse = serializer.ReadObject(rstrm) as UploadAvatar;

feed = postResponse;

localSettings.Remove("avatar");

localSettings.Add("avatar", postResponse.link);

}

}

catch (Exception ex)

{

}

}, null);

}, null);

MessageBox.Show("Ваш аватар успешно обновлен");

}

}

Если коротко мы превращаем выбранное изображение в поток,а поток кодируем в base64 и отправляем на сервер в виде одного из аргументов.

Теперь посмотрим на серверную часть:

if (isset($_POST['avatar']))

{

$date=time();

$img = base64_decode($_POST["avatar"]);

$im = imagecreatefromstring($img);

if ($im !== false) {

header('Content-Type: image/png');

imagepng($im,"/public/avatars/".$date.".jpg");

imagedestroy($im);

}

else {

echo 'An error occurred.';

}

}

$avatar = $date.".jpg";

$responce["success"] = 1;

$responce["link"] =  "http://mysite.com/public/avatars/".$avatar;

$responce = json_encode($responce);

echo $responce;

Сервер принимает пост, и декодирует Base64 и штатными методами создает изображение и сохраняет там где нам нужно. И сервер отвечает json.

Теперь поговорим немного о получении и десериализации ответа сервера.

Вас немогли не ввести в недоумение эти строчки:

feed = new UploadAvatar();

var serializer = new DataContractJsonSerializer(typeof(UploadAvatar));

var postResponse = serializer.ReadObject(rstrm) as UploadAvatar;

feed = postResponse;

Скажу сразу, чтобы получить и сохранить ответ сервера нужен идентичный ответу, класс. Например в  нашем случае Upload avatar:

public class UploadAvatar

{

public int success { get; set; }

public string link { get; set; }

}

И как мы видим наш класс полностью идентичен ответу сервера.

$responce["success"] = 1;

$responce["link"] =  "http://mysite.com/public/avatars/".$avatar;

$responce = json_encode($responce);

echo $responce;

Вот и вся магия.

С вами был я. Подписываетесь на мой твиттер: @khojabergen

Оцените пост

0