synch vk #1. Добавление фотографий в vk перемещением в папку

Сегодня сделаю такую фишку, как автоматическая отправка фотографий в группу, простым закидыванием фотки в папку. Что-то вроде Mail Cloud'а или dropbox клиента, только у нас синхронизация будет не с серверами mail или dropbox, а с группой vk. А что? Тоже весьма надёжное место для хранения фотографий (в нашем случае не хранения, а обычной публикации.) :).

Если подумать, то можно догадаться, что при заливании новой фотографии в папку, размер сей папки меняется. (Загорелась лампочка, осенившая: а ведь так можно отлавливать, когда закинута новая фотка!). Так же можно догадаться, что у каждой фотографии есть своё имя. При появлении новой в группе, её имя будет проверяться с массивом имён уже закинутых фотографий, и если такой нет в массиве, то отправляем её в альбом, а имя ложим в массив. Идея простая, а приложение - полезное :)

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

Итак, сначала забиндим процедуру, которая даст нам выбор папки для фотографий, и запишет в ini-файл её размер, а в текстовик имена файлов:

В var:

  ini: TIniFile;
  dir: String;
  path_ini: string;
  file_settings: File;
  file_name: TextFile;
  namefiles: TStringList;


procedure searchsize;
  var
  mnf: array [1..1000] of string;
  size: Int64;
  List: TStringList;
  I: Integer;
begin
AssignFile(file_settings, ExtractFilePath(Application.ExeName)+'init.ini');
Rewrite(file_settings);
CloseFile(file_settings);
 
AssignFile(file_name, ExtractFilePath(Application.ExeName)+'list.txt');
if FileExists((Application.ExeName)+'list.txt') = false then Rewrite(file_name);
CloseFile(file_name);
 
List:= TStringList.Create;
if ini.ValueExists('file','directory_root') = false  then
begin
  SelectDirectory ('Выберите папку для сохранения фотографий', 'C:\', dir);
  ini.WriteString('file','directory_root',dir); // INI : пишем имя дирректории для изображений
  List:= GetAllFiles(dir);
end;
size:=0;
GetDirSize(dir, size);
ini.WriteInteger('file', 'size_one', size); // INI: пишем первоначальный размер файла
 
{записываем имена файлов в текстовик}
 
Append(file_name);
for I := 0 to list.Count-1 do
begin
ShowMessage(list.Strings[i]);
writeln(file_name, list.Strings[i]);
end;
CloseFile(file_name);
end;


Для определения размера дирректории служит процедура GetDirSize (путь до дирректории, переменная (в которую ляжет размер));

GetDirSize:

Функция, собирающая в стринглист имена всех файлов:

function GetAllFiles( Path: string): TStringList;
var
sRec: TSearchRec;
isFound: boolean;
Lb: TStringList;
begin
Lb:= TStringList.Create;
isFound := FindFirst( Path + '\*.*', faAnyFile, sRec ) = 0;
while isFound do
begin
if ( sRec.Name <> '.' ) and ( sRec.Name <> '..' ) then
begin
if ( sRec.Attr and faDirectory ) = faDirectory then
GetAllFiles( Path + '\' + sRec.Name);
Lb.Add(sRec.Name);
end;
Application.ProcessMessages;
isFound := FindNext( sRec ) = 0;
end;
FindClose( sRec );
Result:= lb;
end;


Запуск, проверка:

Файлы создаются, данные заносятся. Дальше напишем код, который будет определять были ли изменения в папке. В данном случае будем ловить только новые фото, удалённые нас пока, в этой версии программы, не интересуют.

var value_one: integer;
  value_new: int64;
  i, size: Integer;
  path: string;
  namefiles_new, file_old: TStringList;
begin
//привязка переменных к файлам 
AssignFile(file_name, ExtractFilePath(Application.ExeName)+'list.txt');
//Инициализация переменных
namefiles_new:= TStringList.Create;
file_old:= TStringList.Create;
 
value_one:= ini.ReadInteger('file', 'size_one', 0);
path:= ini.ReadString('file', 'directory_root', 'nil');
 
GetDirSize(path, value_new);      //получаем новый размер
if value_new <> value_one then
begin
  namefiles_new:= GetAllFiles(path);     //Получаем список новых имён
  Reset(file_name);
  file_old.LoadFromFile(ExtractFilePath(Application.ExeName)+'list.txt');    //Загружаем список старых имён в стринглист
  //Проверяем, кто новенький:
  for i := 0 to namefiles_new.Count-1 do
  begin
    if pos(namefiles_new.Strings[i], file_old.Text) = 0 then ShowMessage('Новый - '+ namefiles_new.Strings[i]);
  end;
end;
end;


В событии создания формы (OnCreate) у меня прописана инициализация ini-переменной:

ini:= TIniFile.Create(ExtractFilePath(Application.ExeName)+'init.ini');


Кидаем в папку с изображениями какое-либо новое, назовём его к примеру "фото-12". Запускаем, проверяем:

Отловили, отлично.

Теперь на моменте отлова нужно прилепить api-функции, которые загрузят этот самый новый файл на сервера vk, а затем сохранят его в альбом. Напомню, что что бы понять нижеизложенный код, его логику и принцип работы, прочитайте ранее описанные статьи, описанные ранее. Было уже достаточно статей по работе с vk api, как для определённых api-шек, так и описание общего алгоритма работы с api vk.

var
  path, url_no_pars, buf_2, url, server, photos_list, hash, temp : string;
  namefiles_new, file_old: TStringList;
  data: Tidmultipartformdatastream;
  dir: string;

//добавляем в основной блок begin..end:
data:=Tidmultipartformdatastream.Create;
dir:= ExtractFileDir(path);

 if pos(namefiles_new.Strings[i], file_old.Text) = 0 then  // если имя нового файла не найдено в массиве старых, то:
      begin
 
{
ШАГ 1
}
        //Отправляем запрос с методом getUploadServer , который вернёт нам URL для загрузки изображений.
        url_no_pars:= http.Get('https://api.vk.com/method/photos.getUploadServer?album_id=ID_альбома&group_id=ID_группы&access_token='+key+'&v=5.8');
 
        data.AddFile('file1',dir+'\фото\'+namefiles_new.Strings[i], 'image/jpeg');
 
        {парсинг URL}
        for j := 1 to length(url_no_pars) do
          begin
            if url_no_pars[j] = '\' then
            begin
             delete(url_no_pars, pos(url_no_pars[j], url_no_pars), 1);
            end;
 
          end;
          if pos (',"album_id":', url_no_pars) <> 0 then delete(url_no_pars, pos(',"album_id":', url_no_pars)-1, length(url_no_pars));
          url:= copy(url_no_pars, pos('http://',url_no_pars), length(url_no_pars));
         {/парсинг URL}
 
{
ШАГ 2
}
        buf_2:= http.Post(url, data); //передаём изображения (data) на URL, полученный в предыдущем шаге
 
        //Pars HASH
        temp:= buf_2;
        delete(temp, pos('","gid"', temp), length(temp));
        hash:= copy (temp, pos('"hash":"', temp)+8, length(temp));
        //Pars HASH
 
        //Pars server
        delete(temp, pos(',"photos_list', temp), length(temp));
        server:= copy (temp, pos('{"server":', temp)+10, length(temp));
        //Pars server
 
        //Pars photos_list
        temp:= buf_2;
        delete(temp, pos('","aid":', temp), length(temp));
        photos_list:= copy (temp, pos('photos_list":"', temp)+14, length(temp));
        for j := 1 to length(photos_list) do
          begin
            if photos_list[j] = '\'  then delete (photos_list, pos('\', photos_list), 1);
          end;
          ShowMessage(photos_list);
        //Pars photos_list
 
{
ШАГ 3
}
        //Конечная загрузка изображений на сервер
        http.Get('https://api.vk.com/method/photos.save?album_id=ID_альбома&group_id=ID_группы&server='+server+'&photos_list='+photos_list+'&hash='+hash+'&caption=Описание&description=Текст_описания_альбома&access_token='+key+'&v=5.8');
      end;
  end;


Всё таки прокомментирую. Работа с изображениями в vk, а в частности загрузкой и пуликацией, происходит в 3 эпата:

шаг 1) Получение строки с запросом, происходит с помощью отправки запроса с методом getUploadServer. Он вернёт нам URL для загрузки файлов.

шаг 2) Затем на этот адрес отсылаем POST-запрос, где передаём файлы в потоке типа Tidmultipartformdatastream. В итоге получаем в ответ адрес сервера, массив адресов на фото и hash.

шаг 3) Отсылаем финальный запрос на сервер с помощью метода photos.save, передав параметры полученные в шаге 2. Открываем альбом и смотрим:

Это именно то, что я закинул в папку, т.е. что является новым. Осталось добавить лишь добавление имён этих фоток в текстовик, а размера дирректории в ini-файл и кинуть код в таймер. Но с этим, я думаю, вы и сами справитесь :)

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

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

Возможностей усовершенствовать клиента - огромное количество, так что дерзайте!
Теги:
новой, фотографий, можно, dropbox, будет, фотографии, догадаться, сделаю, хранения, папку, осенившая, кодом, лампочка, Загорелась, отлавливать, когда, проекта, новая, закинута, меняется
Добавлено: 24 Февраля 2015 19:28:59 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...