Скажите, что пользователь нажимает на ссылку для загрузки файла. Пользователь получает сохранение как диалоговое окно, но затем нажимает на отмену. Как вы это обнаружите? Если пользователь нажимает на ссылку отмены или не получает весь файл, сервер не должен записывать, что файл был загружен.
Раньше я это делал:
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, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); ob_clean(); flush(); readfile($file); flush() log() exit;
журнал должен запускаться только после того, как readfile будет полным, что означает, что весь файл был передан пользователю. Прошло некоторое время с тех пор, как я это сделал, и я не знаю, где именно точный код, так что это может быть не совсем точно, но это должно вас заставить.
EDIT Я нашел приведенный выше код на php.net, и это более или менее то, что я описывал, этот метод должен работать.
Я думаю, что некоторые HTTPd не регистрируют файлы в журнале доступа до тех пор, пока запрос не будет завершен. Вы можете попробовать написать что-то, что анализирует журнал, greps имя файла и подсчитывает количество строк.
Изменить: просто попробовал с nginx. Подтвердил мою теорию. Я считаю, что то же самое верно для Apache.
Редактировать # 2: Почему это было изменено? На самом деле это правильный ответ в соответствии с дупкой-ссылкой на SO. Я стою оправданным.
Когда сервер отправляет файл, он не просто мгновенно передает по проводам, а пакеты-пакеты, которые должны проходить между клиентом и сервером, отправляют файл за один кусок за раз.
Все, что нужно сделать, это иметь какой-то процесс, который отправляет файл пользователю управляемым образом, так что вы можете подключить событие, где бы «последний» блок файла не был очищен от пользователя.
Теперь предоставлено, пользователь может никогда не получить этот последний блок, но если они спросят о последнем блоке (который делает пакеты ack), то либо они, либо базовый сетевой протокол приняли, что они получили все блоки, предшествующие этому последний блок, и что можно отправить последний блок.
Предположим теперь, что
Все, что вам нужно, это простая конструкция: (Псевдокод).
1: Open File $foo; 2: Loop while $foo is not EOF 3: read 700kilobits from file $foo; 4: print 700kilobits of read data to web server 5: execute webserver 'flush' which blocks until flush is complete. 6: <-- Loop 7: If all chunks of 700kilobits were read before user aborted transaction 8: report file was downloaded.
Ответ редактора Unkwntech фактически совпадает с моим собственным.
Его ответ, тем не менее, специфичен для PHP, и я хотел бы предложить более общее языковое решение, прежде всего потому, что у меня возникло отвращение к PHP, и мне не нужно писать код для него и настраивать веб-сервер и проверять его работу просто чтобы доказать, что я знаю из опыта работы.
Извинения за то, что они слишком ленивы в этом отношении.
Вы говорите о любом файле? Если это программа, вы можете позвонить ей на сервер при установке? Помимо этого я согласен с Джонатаном, не совсем уверен, что у вас есть к этому доступ.
одним из способов было бы написать некоторый PHP, который обрабатывает фактическое предоставление файла, поставленного в качестве параметра $ _REQUEST. Этот скрипт выполнит фактическую работу по регистрации загрузки