Пользователям достаточно часто приходится заниматься пересылкой больших файлов как внутри локальной сети, так и за её пределы. К примеру, Пьеро нужно выслать Мальвине документацию объёмом 10 гигабайт. Тут на помощь не придет корпоративная почта, так как пользователи обычно не хотят заморачиваться с копированием ссылок и т.п. Если они в одной локальной сети, то поможет расшаренная папка, а если они на разных концах страны… Как правило, приходится пользоваться FTP-сервером, что зачастую не очень удобно, либо интернет-сервисами обмена большими файлами.

Так пришла идея создать удобный и контролируемый сервис для пересылки больших файлов в локальной сети.

Реализация на PowerShell, платформа Windows.

Требования:

  • Веб сервер опубликованный в интернет.
  • Расшаренная папка на компьютере под Windows (для определения владельца файла).
  • Настройка на сервере с шарой выполнения скрипта по расписанию, раз в минуту.

Как это работает:

  • Пользователь помещает ZIP архив в расшаренную папку на сервере.
  • Скрипт ищет ZIP-файлы в расшаренной папке и перемещает их в папку веб-сервера, затем отправляет письмо Владельцу файла.
  • Пользователю приходит письмо со ссылкой на скачивание файла через ваш веб-сервер.
  • Пользователь пересылает письмо со ссылкой на скачивание адресату.


Описание работы скрипта:

  • Удаление в целевой папке всего, что не имеет расширения ZIP.
  • Получение списка ZIP-файлов в целевой папке.
  • Перебор ZIP файлов с обработкой каждого файла функцией Send_URL.
  • Функция Send_URL: определяет Владельца файла, обрабатывает имя файла, перемещает файл под новым именем в папку веб-сервера, высылает Владельцу и Администратору (для контроля) на почту ссылку на скачивание файла, удаляет файлы в папке веб-сервера старше определенного количества дней. Более подробные комментарии смотрите в скрипте.
  • Создание файла в расшаренной папке с именем-подсказкой «только ZIP архив, остальное удаляется.txt».

Примечание: если пользователь входит в группу Администраторы на сервере с расшаренной папкой, то Владелец = группе Администраторы, для этого в скрипте указывается административный почтовый ящик.

В скрипте необходимо поменять следующие параметры на требуемые вам:

$path = "C:\UPLOAD\" #Расшареная папка на сервере
$path1 = "C:\inetpub\wwwroot\UPLOAD\" #Папка на веб-сервере, откуда скачивают

В функции Send_URL изменить параметры:

$day = -30 #Вы можете скачать файл в течении "+(-1*$day)+" дней. Затем файл будет удален с сервера.
$mail_domain = "@mydomain.com"
$owner_domain = "mydomain\\"
$mail_admin = "admin@mydomain.com"
$mail_server = "mail.mydomain.com"
$http = "http://web.mydomain.com/UPLOAD/"

Корректное определение владельца файла возможно только в домене. Без домена вам придется завести учетные записи пользователей на компьютере с расшаренной папкой и ассоциировать их с вашими пользователями.

Код:


#Файл Func.ps1 ###################################

# Смирнов Александр Николаевич hars@bk.ru декабрь 2015г.

Function Send_URL($File,$path,$path1){

	### Параметры которые необходимо поправить на свои
	##################################################
    $day = -30 #Вы можете скачать файл в течении "+(-1*$day)+" дней. Затем файл будет удален с сервера.
	$mail_domain = "@mydomain.com"
	$owner_domain = "mydomain\\"
	$mail_admin = "admin@mydomain.com"
	$mail_server = "mail.mydomain.com"
	$http = "http://web.mydomain.com/UPLOAD/"
	##################################################
	

    $File_nm = $File.Trim() # Удаление пробелов в начале и в конце в имени файла
	
    $File = $File -replace '\[|\]','`$0'	# Замена [] на корректные символы

    $owner = ( Get-Acl ($path + $File) ).Owner # Владелец файла
	
    ##############	Формирование email

    if( $owner -like "*dministrator*" -or !$owner ){
        $mail = $mail_admin
    }else{
        $mail = ($owner -ireplace($owner_domain,"")) + $mail_domain
    }

    ######################################

    #$md5 = Get-FileHash ($path + $File) -Algorithm MD5
    #$File_url = $md5.Hash + ".zip"
    #$File_new = $path1 + $md5.Hash + ".zip"

	############# Ограничение размера имени файла
    if($File_nm.length > 100){
        
        $File_url = $File_nm.Substring(0,100)
    }else{
        $File_url = $File_nm
    }
	#############################################
	
    ############# Замена символов @!{}%$#''&`
    $File_url = $File_url -ireplace("#","")
    $File_url = $File_url -ireplace("%","")
    $File_url = $File_url -ireplace("$","")
    $File_url = $File_url -ireplace("&","_")

    $File_url = $File_url -ireplace("{","(")
    $File_url = $File_url -ireplace("}",")")

    $File_url = $File_url -ireplace('`',"")
    $File_url = $File_url -ireplace('"',"")
    $File_url = $File_url -ireplace("'","")

    $File_url = $File_url -ireplace("~","")
    $File_url = $File_url -ireplace(" ","_")
	#########################################

	# Формирование имени файла для публикации в веб
    $File_url = $mail + "_" + $File_url

	# Путь перемещаемого файла	
    $File_new = $path1 + $File_url
	
    # Перемещение файла в веб-папку
    Move-Item -path ( $path + $File ) -destination $File_new -force -EA SilentlyContinue #-whatif 

	# Проверка перемещения файла на случай если он ещё копируется пользователем в папку
    if( Get-ChildItem $File_new -EA SilentlyContinue){
        write-host "OK" #Файл существует
    }else{
        write-host "NO" #Файл не сущетсвует
        break # прерывание функции
    }

	# Размер файла
    $colItems = (Get-ChildItem $File_new | Measure-Object -property length -sum)
    $colSize = "{0:N2}" -f ($colItems.sum / 1MB) + " Mb"

    ######################################
	#Сообщение пользователю
    $Body = "<b>Скачать: </b><a href='" + $http + $File_url +"'>" + $File_nm + " (" + $colSize + ")</a><br/>
    Вы можете скачать файл в течении "+(-1*$day)+" дней. Затем файл будет удален с сервера."

	#Отправка письма
    Send-MailMessage -to $mail -from $mail_admin -subject "Пересылка файлов" -BodyAsHtml $Body -Encoding UTF8 -SmtpServer $mail_server
    
	#Отправка письма администратору, для контроля	
    if($mail -inotlike $mail_admin){
        Send-MailMessage -to $mail_admin -from $mail -subject "Пересылка файлов" -BodyAsHtml $Body -Encoding UTF8 -SmtpServer $mail_server
    }

    Write-Host $owner $mail $Body # Проверка в консоли что кому отправляем

    ######################################
	#Проверка устаревания файлов в веб-папке и их удаление по мере устаревания
    get-childitem $path1 *.zip  | where {$_.lastwritetime -le (get-date).adddays($day) } | del -Recurse -Force
}
##########################################################################################
##########################################################################################
##########################################################################################
##########################################################################################
##########################################################################################




#Файл Send_URL.ps1 ###################################

# Смирнов Александр Николаевич hars@bk.ru  декабрь 2015г.

#В расписание добавить исполнение скрипта раз в минуту
# powershell.exe "C:\Scripts\Send_URL.ps1" -NoLogo -NonInteractive -WindowStyle Hidden

<#
."C:\scripts\Func.ps1" # Подгружаем файл с функциями. Лучше подгружать функции(процедуры), так красивее.
#>
### Параметры которые необходимо поправить на свои
##################################################
$path = "C:\UPLOAD\" #Расшареная папка на сервере
$path1 = "C:\inetpub\wwwroot\UPLOAD\" #Папка на веб-сервере, откуда скачивают
##################################################

# Удаляем все кроме ZIP файлов
Get-ChildItem $path -Recurse -Exclude *.zip | %{ Remove-Item $_ -Force -Recurse } 

# Получаю имена файлов в папке
$flist = get-childitem $path"*.zip" #-recurse 

# Перебор ZIP файлов, перемещение и отсылка владельцу файла письма со ссылкой
$flist | ForEach-Object{ Send_URL $_.PSChildName $path $path1 } 

# Заново копируем html перенаправляющий на сайт 
#В файле index.html строчка перенаправления, для "невозможности" просмотра папки в браузере
#<html><head><meta http-equiv="refresh" content="0;url=http://www.yandex.ru" /></head></html>
#copy C:\inetpub\wwwroot\index.html C:\inetpub\wwwroot\UPLOAD\index.html -Force 

# Создание файла с именем-подсказкой, для особо одаренных
New-Item $path"только ZIP архив, остальное удаляется.txt" -type file -Force 

Комментарии (10)


  1. click0
    05.02.2016 15:36

    Попробуйте использовать вебсервер на nginx.
    И сделать подчиненные nginx сервера с корнями в расшаренные папки.
    А с основного вебсервера, через try_files опрашивать подчиненные сервера.


  1. Kitsok
    05.02.2016 18:32

    Делал такую штуку на FreeBSD, sed и awk в 1997 году.


  1. BoNi
    06.02.2016 09:57

    Мысли у админов схожи, да и инструменты одни и те же…
    Делал год назад — практически один в один с вашей (powershell, веб-сервер, письма шлем владельцу файла). Единственное серьезное отличие — папка не сканируется раз в минуту, а на нее вешается System.IO.FileSystemWatcher. И проблему с *dministrator* обходить не стал, лень было :)


    1. hlgroup
      06.02.2016 10:46

      Согласен. Открытия тут никакого нет, но как ни крути для кого-то есть :)


      1. zolti
        07.02.2016 14:21

        а может есть смысл заставить скрипт создавать zip архивы, если пользователь сам не сумел этого сделать?


        1. hlgroup
          07.02.2016 17:34

          Тогда очень велика вероятность получения бардака. Пользователи в таком случае начнут «умничать»: создавать свои папки, а потом в них закидывать, то что им надо — соответственно надо будет выяснять в какой момент запускать скрипт. При срабатывании скрипта Пользователь начнет орать, что он ещё не дозакинул или ещё хуже при копировании папки или файлов у него вылезла ошибка типа «Длинные имена файлов» и т.п. — одни проблемы на пустом месте. Поэтому было принято решение, что пользователь закидывает в папку ZIP-архив, который потом сможет открыть любой адресат, даже без специальной программы.
          В папку одновременно могут закинуть свои файлы несколько пользователей, а теперь представьте этот сценарий. А если 1 пользователь хочет отправить 2-3 разных папки разным адресатам и все это + то что написано чуть выше. Сложности возникающие при таких сценариях не стоят усилий по их преодолению.
          Так что пусть пользователи «сумеют» создать ZIP-архив и закинуть в папку, но да такие «пользователи» в природе существуют.


  1. das
    09.02.2016 10:56

    reep.io вот им бы только еще сделать расширение для хрома чтобы можно было раздавать при закрытой вкладке или даже закрытом хроме, ну и простой менеджер управления раздачами прямо из браузера.