Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Download файлов (https://javascript.ru/forum/server/25139-download-fajjlov.html)

greatilya 26.01.2012 19:23

Download файлов
 
[это можно не читать]
Сейчас в меня полетят камни мол как можно задавать такие тривиальные вопросы ... но видимо без пинка в нужном направлении разобраться не смогу.

Задача простая, есть ОООООчень много небольших файлов на серверах, поскольку это облачное хранилище то доступ к ним логичнее осуществлять через банальный http. Мне нужно написать скрипт для их скачивания(для бекапа).
[/это можно не читать]

Итого имеется куча http адресов файлов, их нужно скачать. Проблема заключается в том, что я не представляю как опеределить что файл закачан полностью? Чтобы отрубания сервера, или проблемы с интернетом и т.п. не влияли на файлы, и недокаченные файлы качались заново. А, ну да, пишется это всё на PHP.

Заранее спасибо.

melky 26.01.2012 20:24

обычно целостность определяют по контрольной сумме (md5) файла.

проблема только в том, чтобы высчитать md5 для файла в источнике.

greatilya 26.01.2012 21:29

Цитата:

Сообщение от melky
проблема только в том, чтобы высчитать md5 для файла в источнике

вот и я думаю как это сделать... ведь если мы просто считаем этот файл, то нет гарантии что нам файл выдался до конца, и не произошло обрывов связи. Хотя если подумать то наверное что-то вроде этого должно стабильно работать:
function safe_copy($source_file, $destination_file) {
	if(!$sMD5_step1=@md5_file($source_file)) return false;
	if(!@copy($source_file, $destination_file)) return false;
	if(!$sMD5_step2=@md5_file($destination_file)) return false;
	if($sMD5_step1!==$sMD5_step2) return false;
	return true;
}

Как я понимаю, тут получилась двойная проверка, т.к. по сути здесь 2 запроса на сервер: md5_file($source_file) и copy($source_file, $destination_file). А при проблемах со связью он не может дважды выдать файл одинаково неполный.

melky 26.01.2012 22:02

хм.. на сервере нельзя это высчитывать? это бы помогло избежать этой трудности.

greatilya 26.01.2012 22:20

Цитата:

Сообщение от melky
на сервере нельзя это высчитывать? это бы помогло избежать этой трудности.

нет, там конечно можно получать доступ через API, там и должны быть md5 хеши, но при работе через API время работы скрипта значительно увеличивается, причем трафик тоже значительно больше потребляется.
Иными словами не подходит для моей конкретной задачи, поэтому ограничиваюсь http запросами.

melky 26.01.2012 22:25

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

greatilya 26.01.2012 22:40

melky,
видимо я Вас не до конца понимаю. Разве функция которую я написал выше не дает достаточную уверенность что файл скачан верно? Ну и тогда файл получается мы скачиваем 2 раза по http, и 1 раз локально проверяя md5. Или я что-то упустил?

melky 26.01.2012 22:58

да нет, всё верно. а если результаты отличаются (1 и 2), то как вы опознаете, какой файл скачен верно? придётся скачивать ещё раз.

greatilya 26.01.2012 23:10

Цитата:

Сообщение от melky
да нет, всё верно. а если результаты отличаются (1 и 2), то как вы опознаете, какой файл скачен верно? придётся скачивать ещё раз.

а тут на мой взгляд уже не важно. Если функция вернула FALSE, значит файл скачать не удалось, и нужно попробовать скачать заново но позже. Поскольку данная ситуация будет возникать крайне редко, то тут можно обычную обработку с очередью заданий на скачивание. Иными словами это уже "дело техники", реализаций придумать можно много.
Спасибо!

B@rmaley.e><e 26.01.2012 23:48

При ответе на запрос веб-сервер обычно отправляет в ответе заголовок Content-Length. Вот и сверяйте размер файла с ним.

greatilya 27.01.2012 09:46

B@rmaley.e><e,
Примерно так?
function safe_copy($source_file, $destination_file) {
	if(!$aHeaders=@get_headers($source_file, 1)) return false;
	if(!$iSize1=$aHeaders['Content-Length']) return false;
	if(!@copy($source_file, $destination_file)) return false;
	if(!$iSize2=@filesize($destination_file)) return false;
	if($iSize1!=$iSize2) return false;
	return true;
}

B@rmaley.e><e 27.01.2012 10:13

Да.

devote 27.01.2012 20:29

function curl_download( $url, $file ) {
    // открываем файл, на сервере, на запись
    $dest_file = @fopen( $file, "w" );
   
    // открываем cURL-сессию
    $resource = curl_init();

    // устанавливаем опцию удаленного файла
    curl_setopt( $resource, CURLOPT_URL, $url );
    
    // устанавливаем место на сервере, куда будет скопирован удаленной файл
    curl_setopt( $resource, CURLOPT_FILE, $dest_file );
    
    // заголовки нам не нужны
    curl_setopt( $resource, CURLOPT_HEADER, 0 );
    
    // выполняем операцию
    curl_exec( $resource );

    $error = curl_errno( $resource );
    
    // закрываем cURL-сессию
    curl_close( $resource );
    
    // закрываем файл
    fclose( $dest_file );

    return $error;
}

melky 27.01.2012 23:01

devote, разве CURL сможет понять, когда связь оборвалась, а когда файл скачан верно \ неверно ?

devote 27.01.2012 23:09

Цитата:

Сообщение от melky (Сообщение 153485)
devote, разве CURL сможет понять, когда связь оборвалась, а когда файл скачан верно \ неверно ?

Ну если будет использоваться Content-Length то-есть если сервер пришлет длину контента, и курл получит меньше чем положено, то вернет ошибку. Если же сервер будет возвращать контент в виде кусков (chunks) то ошибка может возникнуть в том случае если кусок не удовлетворяет своей длине. Обычно такие ошибки CURL нормально воспринимает. Но если сервер отдаст вместо файла что-то другое, например HTML страницу, то CURL ничего не скажет. Тут нужно проверять заголовки, а точнее в идеале лучше и то и другое делать.

melky 27.01.2012 23:12

Цитата:

Сообщение от devote (Сообщение 153491)
Ну если будет использоваться Content-Length то-есть если сервер пришлет длину контента, и курл получит меньше чем положено, то вернет ошибку. Если же сервер будет возвращать контент в виде кусков (chunks) то ошибка может возникнуть в том случае если кусок не удовлетворяет своей длине. Обычно такие ошибки CURL нормально воспринимает. Но если сервер отдаст вместо файла что-то другое, например HTML страницу, то CURL ничего не скажет. Тут нужно проверять заголовки, а точнее в идеале лучше и то и другое делать.

вот этой мелочи я не знал. мало изучал php.

x-yuri 28.01.2012 18:05

да и функции типа md5_file и copy должны возвращать ошибки. Вообще непонятно, откуда взялись идеи о том, что файл может неправильно скачаться. TCP стал ненадежным протоколом?

Цитата:

Сообщение от greatilya
поскольку это облачное хранилище то доступ к ним логичнее осуществлять через банальный http

1) почему? 2) разве это не обязанность облачных хранилищ, брать на себя заботу о надежном хранении данных?

greatilya 02.02.2012 19:47

Цитата:

Сообщение от x-yuri
TCP стал ненадежным протоколом?

Нет, интерент по "телефонной лапше" не начинал быть надежным :)
Цитата:

Сообщение от x-yuri
1) почему?

Потому что если скачивать файлы посредством API предварительно пройдя авторизацию, конечно можно быть уверенным в правильности копирования файла, но этот способ не является для меня приемлемым, так как:
1. при этом на авторизацию и прочие "движняки" потребляется куда больше трафика - следовательно затрачивается значительно времени.
2. для авторизаций и прочих "движняков" требуется затрачивается также исходящая скорость(в смысле в большем объеме чем при загрузке по http). Это я проверял, потребление исходящего трафика там достаточно большое(это некая особенность API). А у меня входящий трафик 8Мбит, исходящая 0,5Мбит. Следовательно все варианты с затратой исходящего трафика мне не подходят.
Если помножить 1 и 2 пункты на миллины мелких файлов, то получается что каждая сотая секунды "на счету". Пока удалось добиться загрузки со скоростью порядка 1 секунды на файл, позже подумаю как увеличить скорость за счет многопоточного Curl.
Цитата:

Сообщение от x-yuri
2) разве это не обязанность облачных хранилищ, брать на себя заботу о надежном хранении данных?

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

x-yuri 03.02.2012 02:42

Цитата:

Сообщение от greatilya
Нет, интерент по "телефонной лапше" не начинал быть надежным

TCP гарантирует целостность передаваемых данных. Это значит, что либо информация корректно передалась, либо не передалась. Других вариантов нету.

greatilya 03.02.2012 15:02

Цитата:

Сообщение от x-yuri
TCP гарантирует целостность передаваемых данных

Правильно ли я понял? Если даже используем функцию copy, и если в процессе копирования интернет либо сервер с файлом отрубится, то функция вернет false?

x-yuri 03.02.2012 17:43

в первую очередь TCP "вернет" false, а потом и функция copy должна вернуть FALSE.

greatilya 03.02.2012 22:30

x-yuri,
спасибо!


Часовой пояс GMT +3, время: 18:58.