@f_u_s_s
Любопытный кодер

Как добавлять описания к загружаемым фотографиям в альбом VK?

Есть скрипт, который грузит до 5 (максимум который позволяет VK API) фотографий. Загрузка по документации:
1. получить токен
2. получить ссылку для загрузки на сервер
3. отправить POST запрос с файлами
4. после загрузки сохранить методом photos.save

Вот на 4м пункте затык. Мне нужно к каждой фотографии определенное описание добавлять, а метод photos.save, судя по документации, умеет только ко всему пулу фотографий описание клепать. Как приписывать описание в моем случае? Хотелось бы избежать POST-запросов в цикле по одному файлу.

Функция загрузки:
public static function uploadImages($files, $group_id, $album_id)
    {

        //Получаем сервер для загрузки изображения
        $params = array(
            'group_id'  =>   $group_id,
            'album_id'  =>   $album_id
            );
        $api_res = self::queryApi("photos.getUploadServer", $params);

        try
        {
            if($api_res)
            {
                $server = $api_res->response->upload_url;
                $post = array();

                    $query = self::$connection->query("SELECT * FROM `images` WHERE `id` IN (".$files.");");
                    if($query)
                    {
                        $i = 1;
                        while($row = $query->fetch_assoc())
                        {
                            if(!empty($row['image'])){
                                if(file_exists(config::$full_path.'images//'.$row['image'])){
                                    $img = $row['image'];
                                }else{
                                    $img = 'no-image.jpg';
                                }
                            }else{
                                $img = 'no-image.jpg'; 
                            }

                            $post['file'.$i] = new CURLFile(config::$full_path.'images/'.$img);
                            $i++;
                        }
                    }else
                        throw new Exception("Ошибка при запросе в базу данных. Error: ".self::$connection->error, 1);


                if($ch = curl_init($server))
                {
                    curl_setopt($ch, CURLOPT_POST, true);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
                    $json = json_decode(curl_exec($ch));
                    curl_close($ch);

                    $params_save = array(
                            'server'    =>  $json->server,
                            'photos_list'   =>  $json->photos_list,
                            'album_id'  =>  $album_id,
                            'hash'  =>  $json->hash,
                            'group_id'   =>  $group_id,
                            'caption'   =>  'test message for checking uploading photos to VK.com'   //вот это описание припишется ВСЕМ фотографиям, загружаемым в одном запросе
                        );

                    $photo_save = self::queryApi('photos.save', $params_save);

                    if($photo_save)
                    {
                        return $photo_save;
                    }
                    else throw new Exception("При сохранении фотографий в альбом произошла ошибка.", 1);
                }
                else throw new Exception("Ошибка инициализации cURL", 1);
            }
            else throw new Exception("При обращении к API photos.getUploadServer произошла ошибка.", 1);
        }catch(Exception $e){
            echo $e->getMessage();
            return false;
        }
    }


Функция обращения к API:
public static function queryApi($api, $params = null, $type = 0)
    {

        //своеобразный костыль-хак, чтоб не писать отдельную функцию для авторизации =)
        //если пришел 0-обращение к АПИ, если что-то другое (1) - попытка авторизации
        if($type == 0)
        {
            $server = 'https://api.vk.com/method/';
        }else{
            $server = 'https://oauth.vk.com/';
        }

        $params['access_token'] = $_SESSION['vk']['access_token'];
        $params['v'] = config::$vk_api['ver'];

        $postparams = http_build_query($params);

        try{
            if($curl = curl_init()) 
            {
                curl_setopt($curl, CURLOPT_URL, $server.$api);
                curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
                curl_setopt($curl, CURLOPT_POST, true);
                curl_setopt($curl, CURLOPT_POSTFIELDS, $postparams);
                $result = json_decode(curl_exec($curl));
                curl_close($curl);

                if(isset($result->error))
                {
                    //Шаблон для ошибок
                    if($type == 0)
                    {
                        $error_msg = "При запросе к VK API возникла ошибка. ERROR CODE: ".$result->error->error_code."; MESSAGE: ".$result->error->error_msg;
                    }else{
                        $error_msg = "При попытке авторизации произошла ошибка. ERROR: ".$result->error."; DESCRIPTION: ".$result->error_description;
                    }

                    throw new Exception($error_msg, 1);
                }
                else
                {
                    return $result;                        
                }

            }
            else
            {
                throw new Exception("Ошибка инициализации модуля cURL.", 1);
            }
        }catch(Exception $e){
            echo $e->getMessage();
            return false;
        }
    }
  • Вопрос задан
  • 1169 просмотров
Решения вопроса 1
@f_u_s_s Автор вопроса
Любопытный кодер
В общем при загрузке пачкой - никак. Реализовал примерно так:
при выборе изображений каждое добавляется в массив JS, затем по клику начинает работать рекурсивный таймер, который отправляет ajax запрос на PHP скрипт. После ответа от PHP, если все успешно - из массива удаляется это изображение и посылается следующее. И так, пока массив не кончится. Накладываются ограничения VK API на количество обращений в секунду, но ничего другого на ум не пришло.
Код JS:
function sendForm(items, group_id, album_id)
	{

			function ajaxQuery()
			{
				$.ajax({ 
				            type: 'POST',   
				            url: 'loader.php',    
				            data: 'action=loadPhoto&group_id='+group_id+'&album_id='+album_id+'&items='+items.splice(0, qps),
				            success: function(result){   
				            	if (result == 'ok') {
				              		item_selected = items.length;
				              		checked.html(item_selected);
				              		alert(result+" : "+loaded);
				              	}
				              	else
				              		alert(result);
				            }
				    	});
			}

		$('body').append('<div class="loading">');
		//осторожно - РЕКУРСИЯ
		var timerId = setTimeout(function tick() {
			if(items.length>0){
				$.when(ajaxQuery()).done(function(){timerId = setTimeout(tick, 1200);});	//вот тут
			}
			else
			{
				clearTimeout(timerId);
				alert("Выбранные товары загружены!");
				loadItems(1);
				loadPagesCount();
				$('div.loading').remove();
			}
		}, 0);
	}


код файла loader.php
require_once './functions.php';
$func = new functions;

if($_POST['action'] == 'loadPhoto' && !empty($_POST['group_id']) && !empty($_POST['album_id']) && !empty($_POST['items']))
{
	$images = explode(",", $_POST['items']);
	for ($i=0; $i < count($images); $i++) { 
		$photo_load = $func->uploadImages($images[$i], $_POST['group_id'], $_POST['album_id']);
		if($photo_load)
			$result = true;
		else
			$result = false;
	}

	if($result)
		echo "ok";
	else
	{
		echo "ERROR:";
		print_r($photo_load);
	}
}


функция uploadImages в классе functions.php:
public static function uploadImages($file, $group_id, $album_id)
    {

        //Получаем сервер для загрузки изображения
        $params = array(
            'group_id'  =>   $group_id,
            'album_id'  =>   $album_id
            );
        $api_res = self::queryApi("photos.getUploadServer", $params);

        try
        {
            if($api_res)
            {
                $server = $api_res->response->upload_url;
                $post = array();

                    $query = self::$connection->query("SELECT * FROM `product`, `product_price` WHERE `product`.`product_id`='".$file."' AND `product_price`.`product_id`='".$file."';");
                    if($query)
                    {
                        while($row = $query->fetch_assoc())
                        {
                            if(!empty($row['product_full_image'])){
                                if(file_exists(config::$full_path.'images/shop/product/'.$row['product_full_image'])){
                                    $img = $row['product_full_image'];
                                }else{
                                    $img = 'no-image.jpg';
                                }
                            }else if(!empty($row['product_thumb_image']))
                            {
                                if(file_exists(config::$full_path.'images/shop/product/'.$row['product_thumb_image'])){
                                    $img = $row['product_thumb_image'];
                                }else{
                                    $img = 'no-image.jpg';
                                }
                            }else{
                                $img = 'no-image.jpg'; 
                            }

                            $product_desc = $row['product_desc'];
                            $product_price = $row['product_price'];

                            //PHP 5.5+ use 'new CURLFile()' PHP 5.4- use @file_path
                            //$post['file1'] = new CURLFile(config::$full_path.'images/shop/product/'.$img);
                            $post['file1'] = '@'.config::$full_path.'images/shop/product/'.$img;
                        }
                    }else
                        throw new Exception("Ошибка при запросе в базу данных. Error: ".self::$connection->error, 1);


                if($ch = curl_init($server))
                {
                    curl_setopt($ch, CURLOPT_POST, true);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
                    $json = json_decode(curl_exec($ch));
                    curl_close($ch);

                    $params_save = array(
                            'server'    =>  $json->server,
                            'photos_list'   =>  $json->photos_list,
                            'album_id'  =>  $album_id,
                            'hash'  =>  $json->hash,
                            'group_id'   =>  $group_id,
                            'caption'   =>  $product_desc.' Цена: '. $product_price . 'руб.'
                        );

                    $photo_save = self::queryApi('photos.save', $params_save);

                    if($photo_save)
                    {
                        return $photo_save;
                    }
                    else throw new Exception("При сохранении фотографий в альбом произошла ошибка.", 1);
                }
                else throw new Exception("Ошибка инициализации cURL", 1);
            }
            else throw new Exception("При обращении к API photos.getUploadServer произошла ошибка.", 1);
        }catch(Exception $e){
            echo $e->getMessage();
            return false;
        }
    }


Надеюсь, что мой способ поможет кому-нибудь )

ЗЫ: в моем случае передавались ID товаров в БД, по которым затем вытаскивалось изображение.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы