Информация для размышлений и споров!
Часто бывает, что нужно отдавать пользователю непостоянную ссылку на файл а временную, то есть ту
ссылку которая будет доступна всем на определённое время, по истечении которого она автоматически
перестаёт существовать.
Есть много программных вариантов сгенерировать такую ссылку, в php это вообще частое явление, но в данном примере мой небольшой скрипт покажет как это сделать элегантно и без
привязки к конкретному серверу или фреймворку.
Суть: Генерировать хэши на удалённых серверах bash-скриптом и на интерфейсе пользователя (интернет магазин,
блог и любой другой сайт раздающий файлы)
К примеру, у меня есть один файловый сервер (обычный бюджетный VPS), на который происходит загрузка файлов.
На этом сервере установлен
Linux, есть доступ по
SSH, установлен веб-сервер
nginx и всё.
Также есть 2 рабочих каталога, один для хранения файлов а другой для раздачи по http (то есть в этот каталог смотрит
nginx).
Код
input_dir='/opt/www/store.mysite.local' // для хранения файлов
output_dir='/var/www/store.mysite.local' // для раздачи по http (то есть в этот каталог смотрит
nginx)
Также на этом сервере, в задачах
cron запущен 1
bash-скрипт (simlink.sh).
- cкрипт выполняет задачу 1 раз в 24 часа в 00:00, после чего все старые ссылки умирают и создаются новые.
ВАЖНЫЙ МОМЕНТ: Время на файловом сервере и на сервере где расположен сам сайт должно быть
синхронизировано.
В момент вывода ссылки пользователю на сайте желательно с помощью
curl проверить доступность файла а уже потом показать ссылку пользователю либо сообщение о временных трудностях на сервере.
В среднем достаточно 5 секунд для генерации нескольких тысяч ссылок.
Задача скрипта получить содержимое каталога
Код
/opt/www/store.mysite.local
и создать на все файлы в этом каталоге
символьные ссылки в каталог куда смотрит
nginx Код
output_dir='/var/www/store.mysite.local'
Пример ссылки на файл /opt/www/store.mysite.local/
cs1.6.exeКод
/var/www/store.mysite.local/50f647eb4d2ac294845a81ebb189ba79/cs1.6.exe
а так ссылка выглядит в браузере
Код
http://store.mysite.ru/50f647eb4d2ac294845a81ebb189ba79/cs1.6.exe
это
симлинк который расположен в каталоге
Код
/var/www/store.mysite.local
Вот содержимое моего скрипта с комментариями:
Код
#!/bin/bash
solt='F7b60vnYr' # Соль для наглядности
input_dir='/opt/www/store.mysite.local' # Каталог где будут лежать файлы
output_dir='/var/www/store.mysite.local' # Каталог символьных ссылкок
# Если каталог output_dir отсутствует, то создаём его
if [ ! -d "$output_dir" ]; then
mkdir -p $output_dir
fi
# Если каталог output_dir существует, то удаляем со всем его содержимым
if [ -d "$output_dir" ]; then
rm -rf $output_dir/*
fi
# Перебираем файлы в каталоге присвоенный переменной input_dir
for files in "$input_dir"/*
do
# Убираем лишние пути и оставляем только имя файла
file=`echo "$files" | sed "s/.*\///"`
# Получаем md5-хеш на основе значений переменных и текущей даты(день,месяц,год) и убираем в конце "-"
hash=`echo -n $(date +'%d%m%Y')$solt"$file" | md5sum | sed -e 's/ -//'`
# Создаём каталог в виде хеша который мы получили выше и записали в переменную hash
mkdir -p $output_dir/$hash
# Создаём символьные ссылки
ln -s $input_dir/"$file" $output_dir/$hash/"$file"
done
При таком подходе все файлы могут быть распределены по разным серверам а на сайте нужно только
указать имя файла "CS1.6.exe" при создании статьи или к примеру товара. Ещё можно выбрать файловый сервер
store* чтобы
указать на каком сервере лежит файл, это если их у вас > 1.
А вот содержимое того что должно быть на интерфейсе (выдавать конечному пользователю)
В данном примере на php, показан процедурный подход генерации ссылки на интерфейсе.
В ООП создаёте необходимый класс в котором реализуете генерацию хеша по аналогичному принципу.
Интерфейс (просто пример)
Код
<?php
# Процедурный подход реализации примера
$file_name='cs1.6.exe'; // Имя файла
$store='https://store.mysite.ru/';
$solt='F7b60vnY'; // Соль для примера
$time=date('dmY'); // Дата
$var=md5($time.$solt.$file_name); // Формируем хеш файла
echo $var.'<br />'; // Выводим пример хеша
echo '<br /><a href='.$store.$var.'>Download</a>'; // в виде готовой ссылки ссылки
?>
Из плюсов, генерация тысяч ссылок происходит за секунды без необходимости задействовать СУБД.
Файлы не хранятся там где и сам сайт а значит при компрометации сайта файлы не пострадают. А если сами файлы архивировать с парольной защитой то и на удалённом файловом сервере файлы будут в безопасности так как пароли на файлы лежат в БД сайта.
Такой подход также полезен для киносайтов с онлайн просмотром, где достаточно 2-3 сервера во главе с
nginx в качестве балансировщика нагрузки а сами файлы синхронизируются между серверами с помощью
rsync.
НЕМНОГО ТЕОРИИВарианты деплоя/загрузок файлов по серверам это уже другая история которая зависит от проекта, к примеру по
FTP с закачкой только изменённых файлов, в рамках небольшого проекта деплой можно производить с помощью
VSCODE и
Код
#!/bin/bash
FTP_DEPLOY_USER="user@example.com" # FTP User
FTP_DEPLOY_HOST="ftp.example.com" # FTP Host
read -p -s "FTP Password:" FTP_DEPLOY_PASS;
FTP_DEPLOY_DEFAULT="app" # specify a source subfolder (./app)
FTP_DEPLOY_ROOT="" # specify a remote upload folder (/public_html)
ftpPath="${FTP_DEPLOY_DEFAULT}$1"
ftpCommand="open -u $FTP_DEPLOY_USER,$FTP_DEPLOY_PASS $FTP_DEPLOY_HOST;" # open FTP connection
ftpCommand="$ftpCommand set ssl:verify-certificate no;" # disable certificate verification
ftpCommand="$ftpCommand mirror -c --script=/dev/null --verbose=1 --parallel=3" # apply lftp mirror command with 3 parallel uploads
ftpCommand="$ftpCommand --exclude .c9/ " # exclude c9 settings folder
ftpCommand="$ftpCommand --exclude .git/ " # exclude .git folders
ftpCommand="$ftpCommand --exclude wp-admin/ --exclude wp-includes/ --exclude-glob wp-*.php" # exclude WP core
ftpCommand="$ftpCommand --exclude-glob *.zip --exclude-glob *.log --exclude-glob *.ini " # exclude .zip .log .ini
ftpCommand="$ftpCommand --exclude ftp_deploy.sh " # exclude this script
ftpCommand="$ftpCommand -R ${HOME}/workspace/$ftpPath ${FTP_DEPLOY_ROOT}/$ftpPath "
echo "Changes ($ftpPath):"
lftp -c "$ftpCommand"
read -p "Procees with file sync? (y/n) " yn
while true; do
case $yn in
[Yy]* ) lftp -c "${ftpCommand/--script=\/dev\/null/ }"; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
Либо обычная загрузка файла в локальный каталог вашего
WP к примеру загрузке файла выбираем локальный каталог
store1 откуда скриптом загруженный файл переноситься на удалённый файловый сервер ftps://store1.mysite.ru/tmp а уже из каталога tmp этот файл уже местный скрипт переносит в каталог файлов.
Если файл был загружен слуйчайно, то просто загружаем новый с таким же именем, и указываем его на сайте и этот файл будет перезаписан. А если удалили статью то файл можно удалить автоматически с помощью специального скрипта который будет производить сверку из БД сайта с файлами в каталоге на удалённом сервере, получаем список файлов сайта и записываем его в store1.txt далее скриптом делаем в цикле сверку имеющихся файлов в каталоге с файлом который находиться в списке, если его там нет то удаляем.
Отредактировал: Gecko, - 29.12.2021, 20:49
Не отвечаю на ЛС.