Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Simple Download (Bin, ToString und ToFile)


  • Please log in to reply
25 replies to this topic
Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Hallo,

Ich meld mich mal wieder mit ein paar Funktionen:

DownloadToString

DownloadToFile

und

DownloadBin

 

Die Funktionen sollten eigentlich selbsterklährend sein, und ich wollte es auch so einfach und kompakt wie möglich halten.

Daher eben einfach nur die URL als Parameter und keine Header, Methode, etc.

Unterstützt werden die Protokolle HTTP, HTTPS, FTP und Gopher.

Ein Login (htaccess, für FTP oä.) ist mit der user:password kombination möglich, beispiel:

ftp://user:password@hostname.de/eine-datei.txt

 

Achtung: Wird als URL beispielsweise nur "www.hostname.de" angegeben, ist dies nicht korrekt, da das zu verwendende Protokoll in der URL fehlt.

Es muss also "http://www.hostname.de" heissen!

 

Mindestanforderung:

Windows 2000 oder neuer

AHK 1.1+ (ANSI, Unicode, x86 oder x64 ist egal)

 

Für große Downloads empfiehlt sich die Funktion DownloadToFile, da diese Funktion nur das mindeste an Arbeitsspeicher benötigt.

Die anderen beiden Funktionen laden den gesamten Download in den Arbeitspeicher.

 

Ich hab die Funktionen so geschrieben, dass diese voneinander unabhängig sind.

Soll heißen, wenn du zB nur DownloadToString brauchst, musst du nicht extra auch DownloadBin mit einfügen/inkludieren.

 

DownloadToString(url, encoding="utf-8")
{
  static a := "AutoHotkey/" A_AhkVersion
  if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
    return 0
  c := s := 0, o := ""
  if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
  {
    while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
    {
      VarSetCapacity(b, s, 0)
      DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
      o .= StrGet(&b, r>>(encoding="utf-16"||encoding="cp1200"), encoding)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", f)
  }
  DllCall("wininet\InternetCloseHandle", "ptr", h)
  return o
}

DownloadToFile(url, filename)
{
  static a := "AutoHotkey/" A_AhkVersion
  if (!(o := FileOpen(filename, "w")) || !DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
    return 0
  c := s := 0
  if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
  {
    while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
    {
      VarSetCapacity(b, s, 0)
      DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
      c += r
      o.rawWrite(b, r)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", f)
  }
  DllCall("wininet\InternetCloseHandle", "ptr", h)
  o.close()
  return c
}

DownloadBin(url, byref buf)
{
  static a := "AutoHotkey/" A_AhkVersion
  if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
    return 0
  c := s := 0
  if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
  {
    while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
    {
      VarSetCapacity(b, c+s, 0)
      if (c>0)
        DllCall("RtlMoveMemory", "ptr", &b, "ptr", &buf, "ptr", c)
      DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b+c, "uint", s, "uint*", r)
      c += r
      VarSetCapacity(buf, c, 0)
      if (c>0)
        DllCall("RtlMoveMemory", "ptr", &buf, "ptr", &b, "ptr", c)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", f)
  }
  DllCall("wininet\InternetCloseHandle", "ptr", h)
  return c
}


nnnik
  • Members
  • 1625 posts
  • Last active: Apr 11 2017 02:13 PM
  • Joined: 28 Jul 2012

Mal wieder eine grossartige Arbeit Bentschi.

Das istdaswas ich gerade gebraucht habe. THX


Visit the new forum ahkscript.org.

http://ahkscript.org


ruespe
  • Members
  • 567 posts
  • Last active: Dec 01 2014 07:59 PM
  • Joined: 17 Jun 2008

Super, Bentschi. Kurz und knackig!



Seidenweber
  • Moderators
  • 638 posts
  • Last active: Sep 06 2015 01:51 PM
  • Joined: 10 May 2011

+1 - Danke!

Ich bin immer wieder beeindruckt, dass du Code schreibst, der für mich aussieht, wie eine chinesische Tageszeitung, aber etwas nützliches macht.

 

Im Augenblick fehlt mir aber eine Idee, was ich mit DownloadBin() anstellen könnte. Hast du da vll. ein Beispiel? :)


All questions & answers are related to AHK 1.1.19.03 x64 Unicode

 


Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Vielen Dank für das Feedback @ all!

 

Im Augenblick fehlt mir aber eine Idee, was ich mit DownloadBin() anstellen könnte. Hast du da vll. ein Beispiel? smile.png

Es gibt ja Resourcen die man nicht als String herunterladen kann, da diese auch den Null-Terminator schon früher enthalten könnten (Binärdateien wie Bilder, Musik, etc.).

Diese Dateien könnte man sich dann gleich in den Arbeitsspeicher laden, anstatt extra die Festplatte damit bemühen zu müssen.

Bilder könnte man dann so zB. gleich direkt mit GDIP weiterverwenden.



Seidenweber
  • Moderators
  • 638 posts
  • Last active: Sep 06 2015 01:51 PM
  • Joined: 10 May 2011

...gefällt mir gut. Und ich finde es "besseren Stil", als heruntergeladene Dateien zuerst auf die Platte zu schreiben, zu lesen und dann ggf. zu löschen.


All questions & answers are related to AHK 1.1.19.03 x64 Unicode

 


SAPlayer
  • Members
  • 403 posts
  • Last active: Apr 11 2014 04:45 PM
  • Joined: 06 Nov 2012

Eine kleine Frage:

Welche Kodierungen kann ich bei DownloadToString angeben und woher weiß ich, welche ich nutzen muss (z.B. beim Download von HTML-Code)?

Kann man nicht automatisch die Kodierung herausfinden?



Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Die Kodierung darf irgend eine AHK definition sein für StrGet.

Normalerweise sollte UTF-8 passen, wenn nicht kannst du das aus dem HTML-Header auslesen.

 

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    ...
  </head>
...


Gerdi
  • Members
  • 39 posts
  • Last active: Aug 06 2015 11:42 PM
  • Joined: 03 Feb 2013

Danke Bentschi,

 

funktioniert zu Hause klasse,

jedoch im Firmennetz:

 

Intranet-Datei-Inhalte bekomme ich mit obigen Skripts,

Internet-Datei-Inhalte nicht.

 

Lässt sich dies ohne großen Aufwand ändern?

(PS ich habe keine Berechtigung meine Proxy-Einstellungen zu ändern)



Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Ja, du kannst das Script ändern, damit ein Proxy verwendet wird...

in der Zeile 4 wird der DllCall InternetOpen ausgeführt:

if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))

Rot markiert hab ich den Wert der geändert werden müsste.

Aktuell ist in dem Script eine 1, die für INTERNET_OPEN_TYPE_DIRECT steht.

Stellst du den Wert auf 0 für INTERNET_OPEN_TYPE_PRECONFIG, wird ein Proxy verwendet, wenn einer in den Internetoptionen eingestellt wurde



SAPlayer
  • Members
  • 403 posts
  • Last active: Apr 11 2014 04:45 PM
  • Joined: 06 Nov 2012

Gibt es eine Möglichkeit, von einer Seite runterzuladen, bei der Windows das Zertifikat nicht zulässt (im Chrome wird es zugelassen, nur im IE nicht)?

 

Eine http-Verbindung funktioniert leider nicht.



Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Ich hab im 1. Post in den Funktionen INTERNET_FLAG_IGNORE_CERT_DATE_INVALID und INTERNET_FLAG_IGNORE_CERT_CN_INVALID hinzugefügt.

Denke mal damit sollte es funktionieren.



Gerdi
  • Members
  • 39 posts
  • Last active: Aug 06 2015 11:42 PM
  • Joined: 03 Feb 2013

Danke Bentschi,

 

es funktioniert sowohl im Internet als auch im Intranet.



garry
  • Spam Officer
  • 3219 posts
  • Last active: Feb 06 2016 09:32 PM
  • Joined: 19 Apr 2005

danke Bentschi,

ich bin zu blöd um die Funktion zu bedienen

kannst Beispiele zeigen für

-downloadtostring

-downloadBin          ?

 

downloadtofile ist ok

url1=http://www.xav.com/time.cgi
F1  =%A_scriptdir%\test.txt
;---------------------------------------------
downloadtofile(url1,F1)
; downloadtostring
; downloadBin
return



ripper121
  • Members
  • 114 posts
  • Last active: Jan 16 2014 11:06 AM
  • Joined: 01 Nov 2012

THX *-*


Ripper121 aka Ripp3r]D3[
Deutsches (original) Forum: Seit: 11.11.2007 Beiträge: 1912
ripper.gif
Top-10 German