Saturday, 31 August 2019

Download all files listed as links in a local TXT file (Powershell Script)



<#

.Synopsis

Downloads files to a folder with the list of urls already stored in a file.

#>

param(

[CmdletBinding()]


[Parameter(mandatory=$true,

Position=0,

ValueFromPipeline=$true,

HelpMessage="The full path of the list file which has the urls of images.")]

[ValidateScript({Test-Path $_})]

[string]$Path,


[Parameter(mandatory=$true,

Position=1,

HelpMessage="The destination folder where images are to be downloaded to.")]

[ValidateNotNullOrEmpty()]

[string]$Destination,


[Parameter(mandatory=$false,

Position=2,

HelpMessage="Select the keywords, images extensions here, each seperated by commas.")]

[ValidateNotNullOrEmpty()]

[string[]]$SelectList,


[Parameter(mandatory=$true,

HelpMessage="Referer url/website.")]

[ValidateNotNullOrEmpty()]

[string]$Referer,


[Parameter(mandatory=$false,

HelpMessage="Select this to download the images at the -Destination folder.")]

[switch]$CustomDirTree=$false

)###param




begin {

$fileDestination=$null

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

Function Url-ToPath {<#

.Synopsis

Returns the relative directory/file path for the supplied url, so that it can be used to join

any Windows Directory path.

.Parameter

Select -linux to switch to linux type of path.

#>

param(

[CmdletBinding()]


[Parameter(

mandatory=$true,

Position=0,

ValueFromPipeline=$true,

HelpMessage="The url which will be converted to windows(by default) relative path.")]

[ValidateNotNullOrEmpty()]

[string[]]$Uri,


[Parameter(mandatory=$true,

Position=1,

Helpmessage="Main folder path where the path converted from the url will be joined.")]

[ValidateNotNullOrEmpty()]

[string]$Destination,


[Parameter(

mandatory=$false,

Position=1,

HelpMessage="Select this to convert to linux path instead of windows path.")]

[switch]$linux=$false

)

begin{

[string]$specialChars = "?*`"|<>:"

}

process{

###Removing special char for forming legal path.

$actualLink=$Uri -replace ".*//(.*)",'$1'

$rePattern = ($specialChars.ToCharArray() |ForEach-Object { [regex]::Escape($_) }) -join "|"

$actualLink = $actualLink -replace $rePattern,""

###Applying checks...

$actualLink=$actualLink.TrimEnd()

$actualLink=$actualLink.TrimEnd("/")

$path=$actualLink.TrimStart("/")

$Destination=$Destination.TrimEnd()

$Destination=$Destination.TrimStart()

$Destination=$Destination.TrimEnd("/")

$Destination=$Destination.TrimEnd("\")

if($linux){

$fullPath=([System.IO.Path]::Combine($Destination,$path))

$fullPath=$fullPath -replace "\\","/"

Return $fullPath

}

else{

$fullPath=([System.IO.Path]::Combine($Destination,$path))

$fullPath=$fullPath -replace "/","\"

Return $fullPath

}

}

end{

Remove-Variable specialChars

}

}#######Url-ToPath() ends here.


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

Function Download-FileWithProgress {

<#<#<#https://blogs.msdn.microsoft.com/jasonn/2008/06/13/downloading-files-from-the-internet-in-powershell-with-progress/

author:jniver

modified by:picachu

#>#>#>

param(

[CmdletBinding()]


[Parameter(mandatory=$true,Position=0,

HelpMessage="Complete url of file.")]

[ValidateNotNullOrEmpty()]

[string]$Uri,


[Parameter(mandatory=$true,

HelpMessage="Referer url/website.")]

[ValidateNotNullOrEmpty()]

[string]$Referer,


[Parameter(mandatory=$true,Position=1,

HelpMessage="Full path of destination file with name.")]

[ValidateScript({-not (Test-Path $_) })]

[string]$Destination

)

Begin{



}

Process{



###This code bit was inserted by me.

$localTempFilePath=[System.IO.Path]::ChangeExtension($Destination,"temp")

if(Test-Path $localTempFilePath){

try{

Remove-Item $localTempFilePath

}

catch{

Return $false

}

}

elseif(-not (Test-Path ([IO.Path]::GetDirectoryName($Destination)))){

New-Item ([IO.Path]::GetDirectoryName($Destination)) -ItemType Directory -Verbose -InformationAction Continue | Out-Null

}

####above code bit was inserted by me.

$uriObject = New-Object "System.Uri" "$Uri"

$request = [System.Net.HttpWebRequest]::Create($uriObject)

if(-not [string]::IsNullOrWhiteSpace($Referer)){

$request.Referer="$Referer"

}

$request.set_Timeout(6000) #15 second timeout

$response = $request.GetResponse()

if(-not [string]::IsNullOrEmpty($response)){

$totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)

###Write-Output "Length is $totalLength KB"

$responseStream = $response.GetResponseStream()

$responseStream.ReadTimeout=60000###60sec

<#<#<##############Appended codes

Problem with the code when the download file is less than 1024 bytes.

Corrected by doing an If/else statement that checks for file length less than 1024:

#>#>#>

$responseContentLength = $response.get_ContentLength()

if(-not ($responseContentLength -lt 1024))

{

$totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)

}

else

{

$totalLength = [System.Math]::Floor(1024/1024)

}

#######Appended codes end here

$targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $localTempFilePath, Create

$buffer = new-object byte[] 10KB

try{

$count = $responseStream.Read($buffer,0,$buffer.length)

$downloadedBytes = $count

while ($count -gt 0)

{

$targetStream.Write($buffer, 0, $count)

$count = $responseStream.Read($buffer,0,$buffer.length)

$downloadedBytes = $downloadedBytes + $count

###[System.Math]::Floor($downloadedBytes/1024)

Write-Progress -activity "Downloading file '$($Uri.split('/') | Select -Last 1)'" -status "Downloaded ($([System.Math]::Floor($downloadedBytes/1024))K of $($totalLength)K): " -PercentComplete ((([System.Math]::Floor($downloadedBytes/1024)) / $totalLength) * 100)



}

}

finally{

$targetStream.Flush()

$targetStream.Close()

$targetStream.Dispose()

$responseStream.Dispose()

}

Write-Progress -activity "Finished downloading file '$($Uri.split('/') | Select -Last 1)'"

Return $true

}###if

else{

Return $false

}

}###Process

End{



if(($totalLength -eq [System.Math]::Floor($downloadedBytes/1024)) -and (0 -ne $downloadedBytes)){

Move-Item -Path $localTempFilePath -Destination $Destination

}

Remove-Variable "uriObject"

if($response){

Remove-Variable response

}

Remove-Variable "request"

}

}###########Download-FileWithProgress() ends here.


}###begin

process {

Write-Information -MessageData "`n--------------->Beginning Download session of $Path" -Verbose -InformationAction Continue

foreach($url in Get-Content $Path){

$url=$url.TrimEnd()

$filePath=Url-ToPath -Uri $url -Destination $Destination

$fileName=([System.IO.Path]::GetFileName($filePath))

[String]$folderName=([System.IO.Path]::GetFileNameWithoutExtension($Path))

$folderName = $folderName.Replace("List","")

$customFilePath=([System.IO.Path]::Combine($Destination,$folderName,$fileName))

if($CustomDirTree){


if(-not (Test-Path ([System.IO.Path]::GetDirectoryName($customFilePath)))){

New-Item -Path ([System.IO.Path]::GetDirectoryName($customFilePath)) -ItemType Directory | Out-Null

}

if(Test-Path $filePath){Copy-Item -Path $filePath -Destination $customFilePath}

$fileDestination = $customFilePath


}

else{

if(-not (Test-Path ([System.IO.Path]::GetDirectoryName($filePath)))){

New-Item -Path ([System.IO.Path]::GetDirectoryName($filePath)) -ItemType Directory | Out-Null

}

if(Test-Path $customFilePath){Copy-Item -Path $customFilePath -Destination $filePath}

$fileDestination = $filePath

}



if(-not (Test-Path $fileDestination)){

Write-Information -MessageData "Downloading to $fileDestination" -Verbose -InformationAction Continue

###Command for downloading.

if([string]::IsNullOrWhiteSpace($Referer)){

Download-FileWithProgress -Uri $url -Destination $fileDestination

}

else{

Download-FileWithProgress -Uri $url -Destination $fileDestination -Referer $url

}

###Invoke-WebRequest -Uri $url -UserAgent ([Microsoft.PowerShell.Commands.PSUserAgent]::Chrome)

###.\Download-WithReferer.ps1 -Url $url -Destination $filePath

}

else{

Write-Information -MessageData "$fileDestination Already exist." -Verbose -InformationAction Continue

}

}###foreach()

}###Process

end {



}

No comments:

Post a Comment