Есть смартфоновое приложение, которое загружает с сервера картинки. Появилась необходимость вносить изменения в адрес запроса, чтобы на смартфон загружались другие картинки.
Для этого я попробовал сделать так, чтобы запрос отправлялся не напрямую серверу, а через посредника: через свой php-сайт, который бы генерировал новый url, загружал по нему нужную картинку и передавал ее на обратно смартфон.
Проблема в том, что на стороне клиента не нормальный браузер, а мобильное приложение. Если точнее - gps навигатор. И он ни и в какую не хочет принимать картинки от моего php-конвертера, в то время, как браузер с компьютера прекрасно показывает страничку с нужной картинкой.
Пробовал загружать и отдавать картинку несколькими способами, но результат один: до браузера компьютера новая картинка доходит, а до приложения на смартфоне нет.
Вот несколько примеров по скачиванию файла https://a.tile.openstreetmap.org/0/0/0.png. Если что, то при подключении напрямую по этому url смартфон его прекрасно открывает.
Сначала пробовал просто возвращать картинку через echo
<?php
header ('Content-type: image/png');
$ResultURL = 'https://a.tile.openstreetmap.org/0/0/0.png';
$content = file_get_contents ($ResultURL);
echo $content;
?>
Потом пробовал такой пример с хабра. Это - функция, которая вызывает окно скачивания файла.
<?php
function file_force_download($file) {
$file_headers = @get_headers($file);
if ($file_headers[0] != 'HTTP/1.1 404 Not Found') {
// сбрасываем буфер вывода PHP, чтобы избежать переполнения памяти выделенной под скрипт
// если этого не сделать файл будет читаться в память полностью!
if (ob_get_level()) {
ob_end_clean();
}
// заставляем браузер показать окно сохранения файла
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
// пришлось отключить эту строку:
// с ней почему-то скачивался файл в ноль байт.
//header('Content-Length: ' . filesize($file));
// читаем файл и отправляем его пользователю
readfile($file);
exit;
} else {
echo 'file not found';
}
}
file_force_download("https://a.tile.openstreetmap.org/0/0/0.png");
?>
Затем нашел на гитхабе простенький прокси и попробовал передать через него напрямую и файл и его теги.
<?php
/**
* Простой прокси-сервер на PHP для изучения и модификации данных,
* передаваемых между браузером и сторонним сервером.
*
* Запуск:
*
* указать URL сайта в $base
* php -S 127.0.0.1:9001 proxy.php
*
* После этого в браузере можно открывать http://127.0.0.1:9001/
* и все запросы пойдут через прокси на указанный в $base адрес.
*/
// Для вывода данных в консоль
$stderr = fopen('php://stderr', 'w');
$url = $_SERVER['REQUEST_URI'];
$path = parse_url($url, PHP_URL_PATH);
$query = parse_url($url, PHP_URL_QUERY);
$newPath = ltrim($path, '/');
if ($query) {
$newPath .= '?' . $query;
}
//$base = 'https://someapprentice.github.io/maintaskforlayout/';
//$proxyUrl = $base . $newPath;
$base = 'https://a.tile.openstreetmap.org/0/0/0.png';
$proxyUrl = $base;
$contents = @file_get_contents($proxyUrl /* , false, $context */);
// Получаем заголовки ответа из глобальной переменной (PHP!)
$headers = $http_response_header;
$firstLine = $headers[0];
if ($contents === false) {
fwrite($stderr, "Request failed: $proxyUrl - $firstLine\n");
header("HTTP/1.1 503 Proxy error");
die("Proxy failed to get contents at $proxyUrl");
}
fwrite($stderr, "$proxyUrl - OK: $firstLine\n");
$allowedHeaders = "!^(http/1.1|server:|content-type:|last-modified|access-control-allow-origin|Content-Length:|Accept-Ranges:|Date:|Via:|Connection:|X-|age|cache-control|vary)!i";
// Прокидываем разрешенные заголовки
foreach ($headers as $header) {
if (preg_match($allowedHeaders, $header)) {
fwrite($stderr, "+ $header\n");
header($header);
} else {
fwrite($stderr, "- $header\n");
}
}
echo $contents;
Но ничего не вышло.
Вопрос: что я делаю не так? И как все-таки правильно передавать файлы на php?
PS: Вообще, есть такая мысль, что может буть нужно просто создать для телефона иллюзию, что мой сайт это не сайт вовсе, а сервер с файлами и просто передавать телефону заголовки от настоящего сервера. Только вот как это сделать?
В общем, я сам разобрался.
Мой php-скрипт был на бесплатном хостинге Beget.tech. И, видимо, они производят какие-то манипуляции с заголовками, в результате чего страничка на смартфоне не загружается.
Проблема решилась переездом на другой бесплатный хостинг. Пока что я остановился на Hostiman.ru - там со смартфонами все работает.
А для возврата картинки пользователю стал использовать два метода.
Вариант быстрый. Если изображение не требует обработки, то я просто отсылаю пользователя на новый URL через редирект.
header('Location: ' . $url, true, 302);
Заметил, что приложение на смартфоне умеет обрабатывать всего несколько кодов ответов: 200, 302, 404. Все остальные он тупо обрывает.
Вариант медленный. Чтобы обработать картинку, нужно сначала загрузить ее на сервер.
function load($imageURL) {
$info = getimagesize($imageURL);
$type = $info[2];
$width = $info[0];
$height = $info[1];
switch ($type) {
case 1:
$loadedImage = imageCreateFromGif($imageURL);
imageSaveAlpha($img, true);
break;
case 2:
$loadedImage = imageCreateFromJpeg($imageURL);
break;
case 3:
$loadedImage = imageCreateFromPng($imageURL);
imageSaveAlpha($loadedImage, true);
break;
}
$imageData = [$loadedImage, $type, $width, $height];
return $imageData;
}
Дальше можно выполнять все необходимые преобразования картинки. Однако многие преобразования требуют указывать размер изображения. Чтобы каждый раз не обращаться к файлу, я считываю все необходимые данные при загрузке и отправляю вместе с картинкой в своеобразном пакете $imageData.
После этого можно выводить обработанное изображение пользователю.
function output($imageData, $src) {
$image = $imageData[0];
$type = $imageData[1];
switch ($type) {
case 1:
header('Content-Type: image/gif');
imageGif($image, $src);
break;
case 2:
header('Content-Type: image/jpeg');
imageJpeg($image, $src, 100);
break;
case 3:
header('Content-Type: image/x-png');
imagePng($image, $src);
break;
}
imagedestroy($image);
readfile($src);
exit();
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Всем привет! Столкнулся со странной для меня ошибкой, имеется код:
Есть какое то определенное значение, получаю последнее в нем число, если оно есть прибавляю к нему 1
Пишу чат на php, сообщения отправляются в базу данных mysql и получается достать их оттуда, но проблема в том, что не получается вывести email того...