Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: ajax принимает изображение как обработать?
 
 автор: poli   (23.05.2013 в 09:38)   письмо автору
 
 

не понимаю, можно ли вообще так делать и как правильно.

на страничке есть кнопка, по нажатию аякс-запрос посылает на сервер изображение
xhr.open("post", "doImg.php", true);
xhr.send(form);

файл doImg.php обрабатывает это изображение и возвращает обратно
header('Content-Type: image/jpeg');
imagejpeg($dest);

и вот что теперь делать в функции обрабатывающей ответ сервера ???
xhr.onload = function(data) {
// ???
};

ответ приходит типа
����JFIF��>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality
��C....

я хочу, чтобы генерировалось сохранение в файл на пк пользователя (т.е. появляется стандартное предложение браузера: сохранить файл или открыть...)
Не понимаю как это сделать и возможно ли.
Помогите, пожалуйста, разобраться.
Спасибо!

  Ответить  
 
 автор: confirm   (23.05.2013 в 10:07)   письмо автору
 
   для: poli   (23.05.2013 в 09:38)
 

А разве Ajax может отправлять бинарные данные?

  Ответить  
 
 автор: poli   (23.05.2013 в 10:28)   письмо автору
 
   для: confirm   (23.05.2013 в 10:07)
 

извините, пожалуйста, я не большой дока, не совсем понимаю ваш вопрос.
но момент с отправкой данных у меня работает, вопрос относится к ответу сервера

поменяла код в doImg.php, теперь сервер возвращает картинку в base64
header('Content-Type: image/jpg');
imagejpeg($dest, '1.jpg', 75);
if($fp = fopen('1.jpg',"rb", 0)) 
                    { 
                    $gambar = fread($fp,filesize('oli.jpg')); 
                    fclose($fp); 
}                    
echo "data:image/jpg;base64,".chunk_split(base64_encode($gambar));

функция onload, которая его принимает выводит данные в картинку
xhr.onload = function(data) {
            console.log("Upload complete.");
            var new_img = new Image();
            new_img.src = data.target.responseText;
            window.document.body.appendChild(new_img);
        };

Но я хочу, чтобы браузер предлагал сразу сохранить картинку в файл,
а так придется еще кнопочку ставить "сохранить результат"

  Ответить  
 
 автор: confirm   (23.05.2013 в 10:48)   письмо автору
 
   для: poli   (23.05.2013 в 10:28)
 

Значит вы не верно ставите вопрос - у вас сервер отдает клиенту изображение как кодированную в base64 строку, в ответ на асинхронный запрос, а не наоборот как вы пишите - Ajax посылает на сервер изображение...
Не может он такого сделать просто напросто. Объект используемый в Ajax (текущая версия) отправляет на сервер только текстовые поля, radio/cechbox и кнопки, поля типа file игнорируются, даже если вы передадите соответствующие заголовки. Из современных браузеров передать на сервер изображение в нынешней версии Ajax можно только в Firefox, с помощью нового функционала форм в HTML5. И это можно сделать как раз опять с помощью base64.
Загрузка изображений на сервер посредством Ajax будет поддерживаться в следующей версии (по крайней мере ожидается такое).

Это то, о чем вы не поняли. Что касается сохранить переданное сервером изображение, да еще как строку, сразу на клиенте - этого сделать нельзя без согласия пользователя, вообще ничего нельзя сохранить без его ведома. Так что только если он захочет. Но в вашем случае кнопочка "сохранить результат" не поможет, так как не обладает браузер возможностью сохранять строку некую, которую вы как либо передали. Можно ее только скопировать и сохранить. Можно отдавать пользователю файл, а он будет выбирать "Сохранить как...".

Тоже самое и с вашим изображением - чтобы у пользователя была возможность сохранить это изображение, он должен видеть не кнопочку "сохранить что-то...", ибо для браузера это будет NULL, а видеть изображение. И даже была бы такая возможность, то сохранялось бы не изображение, а строка - не ожидайте, что браузер при этом автоматом бы преобразовал ее в бинарный вид. Если строка base64 описывающая это изображение не превышает определенного размера для конкретного браузера (у каждого свои ограничения), то это изображение можно отобразить на странице, а уже щелкнув по нему, пользователь может выбрать "Сохранить...". По другому никак.

PS. Это

var new_img = new Image();
new_img.src = data.target.responseText;
window.document.body.appendChild(new_img);

заменяется одной строкой

<img src="data:image/ТИП;base64, СТРОКА BASE64....

  Ответить  
 
 автор: poli   (24.05.2013 в 10:52)   письмо автору
 
   для: confirm   (23.05.2013 в 10:48)
 

confirm спасибо за ответ!
но все еще я не понимаю, что же мне нужно прописать в функции-обработчике ответа с сервера.

по поводу передачи файлов ajax - как вы пишете про html5 "ожидается" - будущее уже наступило http://caniuse.com/#search=FormData
по кр. мере я юзаю хром, и кроссплат. меня в данном сл. не интересует.

по поводу "сохранить переданное сервером изображение", мне и не нужно без ведома пользователя, мне нужно чтобы инициировалась обычная загрузка файла, как это происходило бы, не используй я аякс-запроса,

заголовки
header('Content-Type: image/jpeg'); 
header("Content-Disposition: attachment; filename= img.jpg");

предложили бы пользователю загрузить файл (захочет пользователь или нет - его дело, но сейчас это предложение подавляется аяксом - вот в чем проблема)
но у меня аякс, и я не знаю, что мне нужно написать в функции, которая ждет ответ от сервера, потому, что данные-то приходят ( я вижу их в панели разработчика), но естественно никуда не выводятся (так как у меня нет соответ. обработки получаемых результатов).

  Ответить  
 
 автор: confirm   (24.05.2013 в 12:00)   письмо автору
 
   для: poli   (24.05.2013 в 10:52)
 

Вот я и прошляпил расширения XMLHttpRequest 2 в HTML5.

Ну значит вы не так поступаете - плохо, что сервер возвращает строку base64, это и длиннее оригинала в три раза, и если превысит размер допустимый, значит не увидит картинку пользователь. А ведь, если вы читали о новых возможностях, то должны знать, что можно и принимать бинарные данные.

Есть в HTML5 и возможность сохранения принятых данных, но не на диск, как это бы происходило при скачивании, а в локальное хранилище, короче в "песочницу". Все это политика безопасности. Поэтому если сохранить на диск, то можно сохранить файл в сессии, а кнопка это запрос на скачивание файла по параметру (отдача скриптом). Иначе никак.

Если работать не в рамках html-страницы, а в рамках системы (например, речь идет об административном управлении), то можно сохранить и на диск, и все что угодно сделать (у JS не будет ограничений) и без танцев.

  Ответить  
 
 автор: Sfinks   (24.05.2013 в 12:33)   письмо автору
 
   для: poli   (24.05.2013 в 10:52)
 

Если я правильно понял задачу (т.е. по запросу нужно чтоб сервер выдал предложение сохранить картинку), то вам ajax не нужен. Вам нужно:
document.location = 'doImg.php';

А doImg должен работать так, как у вас было в самом начале
<?php
  header
('Content-Type: image/jpeg'); 
  
imagejpeg($dest);

Если у вас ajax'oм отправляется и обрабатывается картинка, то вам нужно не возвращать саму картинку клиенту, а сохранить ее на сервере в какой-нить временной папке и передать клиенту только адрес этого файла. А клиент, получив адрес нового изображения, опять же должен выполнить
document.location = 'temp_img_file.jpg';
при этом никакого перехода не будет, а выскочит именно окно с предложением сохранить картинку.

_______
P.S.
"при этом никакого перехода не будет, а выскочит именно окно с предложением сохранить картинку."
Вообще в этом не уверен.... Если браузер вместо предложения сохранить, перейдет и отобразит картинку, то замените
header('Content-Type: image/jpeg');
на
header('Content-Type: application/octet-stream');

  Ответить  
 
 автор: DangerBay   (24.05.2013 в 13:52)   письмо автору
 
   для: Sfinks   (24.05.2013 в 12:33)
 

Не так всё просто. Там же postом отправляется сначала на обработку файл, а потом нужно получить результат. Сами же написали, что на диск надо сохранять сначала. Средства XMLHttpRequest не позволяют получить ответ с бинарными данными в onload и сразу выдать данные пользователю с нужными заголовками. Хотя решение есть наверно, но не искал.
Можно сделать так (не тестировал)

Заменить
header('Content-Type: image/jpeg');
imagejpeg($dest);


на

      
                       if($_GET['img']){
                              $imgname = (int)$_GET['img'];
                              $filepath = "folder/". $imgname .".jpg";
                              if(file_exists($filepath)) {
                                   header("Content-Type: image/jpeg");
                                   header("Content-Disposition: attachment; filename=". $imgname .".jpg");
                                   readfile($filepath);
                              }
                              exit();
                       }
                      
                       $t = time();
                       imagejpeg($dest, "folder/". $t .".jpg"); 
                       echo $t;

folder - папка сохранения картинок (с правами на запись)

в js:
xhr.onload = function(e) {
document.location = 'doImg.php?img=' + xhr.responseText;
};


И всё по идее.
Второй вариант проще - делать прямое обращение к картинке
document.location = 'temp_img_file.jpg';

но в папке с картинками тогда придется создать .htaccess c содержимым
ForceType application/octet-stream
Header add Content-Disposition "attachment"

но это не на любом сервере будет работать ещё.

  Ответить  
 
 автор: poli   (25.05.2013 в 12:23)   письмо автору
 
   для: DangerBay   (24.05.2013 в 13:52)
 

ребята, спасибо за помощь!
все "срослось" :)
confirm, спасибо за учасите.
Sfinks, спасибо, вы совершенно правильно поняли задачу, дали верное направление решения. сомнения были оправданы:
прямое обращение к картинке
document.location = 'temp_img_file.jpg';  

отображает картинку.

И вы еще раз правы, можно было обойтись без аякса (я теперь тоже это понимаю, но я делала аякс-загрузку, поскольку изображения получала с помощью drag-and-drop, а не стандартного input type="file", теперь, чтобы сделать тоже самое без аякса, нужно доработать js-часть по загрузке изображения на сервер)

DangerBay, спасибо, ваш комментарий помог получить ожидаемый результат. Обращение в document.location к php-файлу - именно то, чего не доставало.

через аякс получилось так
1) js:
оформляю нужные данные и передаю на сервер
xhr.open("post", "doImg.php", true); 
xhr.send(form); 


2) doImg.php:
обрабатывает полученный файл и сохраняет его во врем. файл,
возвращает код файла
код DangerBay (24.05.2013 в 13:52)

3) js:
принимает ответ сервера и просит вернуть обработанное изображение
xhr.onload = function(data) {
            document.location = 'doImg.php?img=' + xhr.responseText;
        };


4) doImg.php?img=:
возвращает обработанный файл
код DangerBay (24.05.2013 в 13:52)
а заголовки "говорят" браузеру вывести окно "Сохранить как..."
что и требовалось...

Без аякса в данном случае, наверное, будет правильнее хотя бы с той т. зрения, что уменьшается колич-во обращений клиента к серверу...
еще раз спасибо, что помогли разобраться.

  Ответить  
 
 автор: DangerBay   (23.05.2013 в 15:15)   письмо автору
 
   для: poli   (23.05.2013 в 09:38)
 

Чтобы браузер предложил сохранить файл:
header('Content-Type: image/jpeg');
header("Content-Disposition: attachment; filename=" . $my_filename ); 
imagejpeg($dest);


в $my_filename имя картинки, например, pic123.jpg

В $dest получение из $_FILES и дальнейшая обработка картинки, но это уже и так есть, как я понимаю.

  Ответить  
 
 автор: poli   (24.05.2013 в 10:54)   письмо автору
 
   для: DangerBay   (23.05.2013 в 15:15)
 

DangerBay, спасибо за заголовки,
но у меня проблема их принять, как уже и написала выше.

т.е. проблема в js-скрипте обработать,
наверное, мне нужно с этим вопросом на форум javaScript?

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования