BitTorrent Download mit Aria2 und Powershell

Im Rahmen von einem Projekt musste ich mich vor kurzem mit einem Dateidownload via BitTorrent intensiv beschäftigen. Dabei hab ich mir ein paar Open Source varianten angeschaut und bin schliesslich bei Aria2 hängen geblieben. Das Aria Projekt bietet eine ganze menge an Protokollen (HTTP, SFTP, FTP ,etc.) an, um Daten herunterzuladen. Bei der Analyse bin auf die RPC Schnittstelle gestossen, über die man Aria quasi fernbedienen kann. Die RPC Schnittstelle kann entweder Json oder XML Datenstrukturen verarbeiten.

Bei testen hab ich schnell ein paar Powershell skripte genutzt, um die Interaktion mit Aria besser zu verstehen. Als Vorbereitung muss man erstmal Aria konfgiurieren, damit die RPC Schnistelle überhaupt verfügbar ist. Man kann entwender alle Konfig-Parameter über die aria.config Datei einstellen oder man gibt einfach ein paar Kommandozeilenparameter beim Starten von Aria mit:

aria2c.exe --enable-rpc --rpc-listen-all

Bei der option –rpc-listen-all geht es nicht um den Port, sondern um das Network-Interface. D.h. ob Aria reagiert auf Call für localhost oder IP. Zum testen kann man einfach alle Interface anschalten und gut. Für später sollte man sich aber die Absicherungsmethoden wie SSL und Secrete-Token mal genauer anschauen.

Mit dem folgenden Powershell-Skript spricht man die RPC Schnittstelle an und übergibt einen Torrent File. Der Torrent File beinhaltet qausi die Informationen, welche Dateien von welchem BitTorrent Server geladen werden soll:

# setting vars
# url points to aria2 rpc host
$url = "http://localhost:6800/jsonrpc"
#path to torrent file
$torrent = "C:\002315_0001.torrent"
#directory to download to
$dir = "C:\\temp\\download"
 
#read the content of torrent file and encode base64
$enc = [convert]::ToBase64String((get-content $torrent -encoding byte))
 
#setting the command for rpc
$command = @"{"jsonrpc": "2.0","id": 11,"method": "aria2.addTorrent", "params": ["$enc",[],{"dir": "$dir"}]}
"@
 
#debug print 
write-host $command
 
#setting the weblient
$bytes = [System.Text.Encoding]::UTF8.GetBytes($command)
$web = [System.Net.WebRequest]::Create($url)
$web.Method = "POST"
$web.ContentLength = $bytes.Length
$web.ContentType = "application/x-www-form-urlencoded"
 
#executing against the rpc
$stream = $web.GetRequestStream()
$stream.Write($bytes,0,$bytes.Length)
$stream.close()
 
#read the responds from rpc
$reader = New-Object System.IO.Streamreader -ArgumentList $web.GetResponse().GetResponseStream()
$json = $reader.ReadToEnd() 
$reader.Close()
 
#convert the repond json in object
$null = [System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$ser = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$obj = $ser.DeserializeObject($json)
 
#looking in the result
$gid = $obj.result
 
#debug print result
write-host $gid

Als erfolgreiche Rückantwort von der RPC Schnittstelle erhält man eine GID zurück. Das ist im Grunde nur ein eindeutiger Schlüssel für den gestarteten Download, über den man im nächsten Schritt abfragen kann, ob der Download fertig ist oder ob es schiefging. D.h. man fragt quasi den Status ab:

# setting vars
# url points to aria2 rpc host
$url = "http://localhost:6800/jsonrpc"
#gid unique identifier for the download job
$gid = "401ffd2682ba057c"
 
$command = '{"jsonrpc": "2.0", "method": "aria2.tellStatus", "params":["$gid"], "id": 1}'
 
#debug print 
write-host $command
 
#setting the weblient
$bytes = [System.Text.Encoding]::UTF8.GetBytes($command)
$web = [System.Net.WebRequest]::Create($url)
$web.Method = "POST"
$web.ContentLength = $bytes.Length
$web.ContentType = "application/x-www-form-urlencoded"
 
#executing against the rpc
$stream = $web.GetRequestStream()
$stream.Write($bytes,0,$bytes.Length)
$stream.close()
 
#read the responds from rpc
$reader = New-Object System.IO.Streamreader -ArgumentList $web.GetResponse().GetResponseStream()
$json = $reader.ReadToEnd() 
$reader.Close()
 
#convert the repond json in object
$null = [System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$ser = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$obj = $ser.DeserializeObject($json)
 
#debug print result
write-host ($obj.result | Format-Table | Out-String)
 
#debug of status
$obj.result["status"]

Im Attribut Status stehen dann klar informationen wie Active, Complete, Error, etc. drinnen. Somit kann man dann entsprechend auf den Status reagieren und entweder die heruntergeladenen Daten im Download Verzeichnis abholen oder entsprechend neuaufsetzen und den Download noch mal starten, falls es einen Fehler gab.

Kleine Tipp noch am Rande, es gibt ein WebUi für Aria, der ebenfalls die RPC Schnittstelle nutzt. Das ist super praktisch wenn man debuggen möchte und man kann sich ein paar Beispiele anschauen, wie man mit der Schnittstelle umgeht falls man mehrere Befehle auf einmal an die RPC Schnittstelle senden möchte. Die Schnittstelle unterstützt nämlich Mulitcalls, d.h. man kann mehrere Befehle in einem Request an den Server stellen und erhält dem entsprechend auf mehrere Json formatierte Rückantworten.

http://www.agile-coding.net/bittorrent-download-mit-aria2-und-powershell/