Мой клиент хотел, чтобы пользователи предлагали загрузки, но только после того, как они заполнили регистрационную форму (в основном имя и адрес электронной почты). Электронная почта отправляется пользователю со ссылками на загружаемый контент. Ссылки содержат хеш регистрации, уникальный для пакета, файла и пользователя, и они фактически переходят на страницу PHP, которая регистрирует каждую загрузку и выталкивает файл, записывая его в stdout (вместе с соответствующими заголовками. Это решение имеет присущие недостатки , но это то, как они хотели это сделать. Надо сказать, что я сильно затруднил их: 1.) ограничил размеры загружаемых файлов и 2.) подумал об использовании CDN (у них есть международные клиенты, но они размещены в США на 2 зеркальных серверах и балансировщик нагрузки, который использует липкие IP-адреса). Во всяком случае, это «работает для меня», но некоторые из их международных клиентов находятся на очень медленных соединениях (скорость d / l ~ 60 кБ / сек), и некоторые из этих файлов довольно большие (150 МБ). Поскольку это PHP-скрипт, обслуживающий эти файлы, он привязан к настройке таймаута сценария. Сначала я установил это на 300 секунд (5 минут), но для некоторых из бета-пользователей это было недостаточно. Итак, я попытался вычислить тайм-аут сценария на основе размера файла, деленного на соединение 100 кбит / с, но некоторые из этих пользователей еще медленнее, чем это.
Теперь клиент хочет просто увеличить значение таймаута. Я не хочу удалять таймаут все вместе, если скрипт каким-то образом попадает в бесконечный цикл. Я также не хочу, чтобы выталкивать тайм-аут произвольно для некоторой скорости соединения с самым низким уровнем общего знаменателя (большинство людей загружаются намного быстрее, чем 100 кб / сек). И я также хочу, чтобы вы могли сказать клиенту в какой-то момент «Посмотрите, эти файлы слишком велики, чтобы обрабатывать этот путь. Вы влияете на производительность остальной части сайта с помощью этих 40-минутных соединений. переосмыслить, как они доставляются или использовать гораздо меньшие файлы ».
У меня есть несколько решений, которые следующие:
Шансы № 1-3 будут отклонены или, по крайней мере, оттолкнуты. Итак, хороший способ сделать это, или есть что-то еще, что я не рассматривал?
(Не стесняйтесь оспорить исходное решение.)
Используйте X-SENDFILE. Большинство веб-серверов поддерживают его либо изначально, либо плагин (apache).
используя этот заголовок, вы можете просто указать путь к локальному файлу и выйти из PHP-скрипта. Веб-сервер видит заголовок и служит для этого файла.
Легким решением было бы отключить таймаут. Вы можете сделать это по запросу:
set_time_limit(0);
Если ваш скрипт не глючит, это не должно быть проблемой – если ваш сервер не сможет обрабатывать столько одновременных подключений из-за медленных клиентов.
В этом случае # 1, # 2 и # 3 – два хороших решения, и я бы пошел в зависимости от того, что дешевле. Ваша озабоченность по поводу №1 может быть уменьшена путем создания токенов загрузки, которые могут использоваться только один раз или в течение небольшого периода времени.
Вариант №4, на мой взгляд, не является отличным вариантом. Скорость может сильно варьироваться во время загрузки, поэтому любая оценка, которую вы бы сделали вначале, была бы, с большой вероятностью, неправильной.
Я немного зарезервирован около # 4. Злоумышленник может подделать поддельный запрос AJAX, чтобы установить таймаут на очень высокое значение, затем он может ввести вас в бесконечный цикл. (Если вас это беспокоит в первую очередь)
Я бы предложил решение, подобное @prodigitalson. Вы можете создавать каталоги с использованием хеш-значений /downloads/389a002392ag02/myfile.zip
которые символически /downloads/389a002392ag02/myfile.zip
к реальному файлу. Ваш PHP-скрипт перенаправляется на этот файл, который обслуживается HTTP-сервером. Симлинк удаляется периодически.
Дополнительным преимуществом для создания каталога вместо файла является то, что конечный пользователь не видит искомое имя файла.
Я думаю, что основная проблема заключается в обслуживании файла thourgh скрипта PHP. Не только у вас будет проблема с таймаутом. Также выполняется процесс веб-сервера, пока файл отправляется клиенту.
Я бы порекомендовал что-то вроде # 1. Это не должно быть CDN, но PHP-скрипт должен перенаправляться непосредственно в файл. Вы можете проверить обход, используя правило перезаписи и параметр, который будет проверять, соответствует ли параметр и текущее время запроса.
Я думаю, что вы можете сделать что-то вроде # 1, за исключением того, что будете хранить его на своих серверах и обходить его напрямую через php. После того, как любое утверждение / утверждение должно произойти с php, этот сценарий создает временную ссылку на файл для dowwnload через традиционный http. Если на * nix id сделать это с помощью символической ссылки на реальный файл и запустить задание cron каждые n минут, чтобы очистить старые ссылки к файлу.
Вы можете создать временный файл на диске или символическую ссылку, а затем перенаправить (используя header()
) в этот временный файл. Затем может появиться cronjob и удалить временные файлы с истекшим сроком действия. Ключевым моментом здесь является то, что каждая загрузка должна иметь уникальный файл временного файла.