Тема: AHK: UrlDownloadToFile с таким же расширением, как и скачиваемый файл.
Как такое замутить без использования сторонних приблуд при условии, что в ссылке на файл расширение не указано.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Серый форум → Общение → AutoHotkey → AHK: UrlDownloadToFile с таким же расширением, как и скачиваемый файл.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Как такое замутить без использования сторонних приблуд при условии, что в ссылке на файл расширение не указано.
Э... Лично я ничего не понял.
Я это понял так. Есть ссылка на скачивание типа http://avatars-fast.yandex.net/get-dire … dkojGA/y90. То есть в ссылке не указано расширение файла (в данном случае .JFIF).
Согласно заданию, скрипт получет ссылку, скачивает файл, самостоятельно определяет расширение и присваивает файлу имя.
Именно это я и имел в виду.
Для конкретного случая:
url = http://avatars-fast.yandex.net/get-direct/R85qdm4hRHr-gA65dkojGA/y90
Type := Request(url).getResponseHeader("Content-Type")
msgbox % "Ext: " SubStr(Type, InStr( Type, "/")+1)
Request(url) {
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WebRequest.Option(6) := False ; No redirects
WebRequest.Open("GET", url, false)
WebRequest.Send()
Return, WebRequest
}
А для общего случая?
На оф.форуме SKAN писал, что:
we may find the filename with a few DllCall()s and then use it with URLDownloadToFile
Но дальше тема заглохла.
На оф.форуме ответили.
И объединив их вариант с вариантом serzh82saratov получилось так:
Download("https://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c")
Download("http://avatars-fast.yandex.net/get-direct/R85qdm4hRHr-gA65dkojGA/y90")
Download(url) {
If (!InStr(url,"://"))
url := "http://" . url
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
ComObjError(false)
WebRequest.Open("GET", url)
WebRequest.Send()
cdHeader := WebRequest.GetResponseHeader("Content-Disposition")
If (cdHeader)
{
RegexMatch(cdHeader, "filename=""([^""]+)""", match)
fileName := match1
}
Else
{
SplitPath, url, fileName, , ext
if (ext = "")
{
ext := WebRequest.GetResponseHeader("Content-Type")
if (ext != "")
filename := filename "." SubStr(ext, InStr(ext, "/")+1)
}
}
UrlDownloadToFile, %url%, %fileName%
}
Нехорошо это, получается файл 2 раза скачивается
http://www.autohotkey.com/board/topic/7 … ntry475484
Download("http://avatars-fast.yandex.net/get-direct/R85qdm4hRHr-gA65dkojGA/y90")
Download("https://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c")
Download(url) {
If (!InStr(url,"://"))
url := "http://" . url
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
ComObjError(false), WebRequest.Open("GET", url), WebRequest.Send()
If (cdHeader := WebRequest.GetResponseHeader("Content-Disposition"))
RegexMatch(cdHeader, "filename=""(?<name>[^""]+)""", file)
Else
{
SplitPath, url, fileName, , ext
if (ext = "" && ctHeader := WebRequest.GetResponseHeader("Content-Type"))
filename := filename "." SubStr(ctHeader, InStr(ctHeader, "/")+1)
}
If StreamToFile(WebRequest.ResponseStream, fileName), WebRequest := ""
MsgBox, %url%`n`n%fileName%
Else
MsgBox Error! File not download in url:`n%url%
}
StreamToFile(Stream, fileName) {
If (ComObjType(Stream) != 0xD)
Return 0
pIStream := ComObjQuery(Stream, "{0000000c-0000-0000-C000-000000000046}")
oFile := FileOpen(fileName, "w")
While (cbRead != 0)
VarSetCapacity(Buffer, 8192)
, DllCall(NumGet(NumGet(pIStream + 0) + 3 * A_PtrSize)
, "ptr", pIStream, "ptr", &Buffer, "uint", 8192, "ptr*", cbRead)
, oFile.RawWrite(&Buffer, cbRead)
Return 1, ObjRelease(pIStream), oFile.Close()
}
Только большие файлы качать не хочет.
Например:
Download("http://dl.firedrive.com/?key=MjBBN0M5OURGMTM2MzRFODoxNDA1MzkxNjY5OmQ2ZDE5MTc4NzFjMzhmNGNjMWY3ZTg4YjA4MjkyZDQ2NTM4ZDJjY2I=")
#MaxMem 4095
С этим тоже?
Да, с этим тоже.
Может быть как-то надо разбивать на части?
http://stackoverflow.com/questions/1844 … g-vbscript
И непонятно, как в вашем варианте сохранять файл не в A_ScryptDir.
Разобрался, как поменять директорию, осталась проблема с большими файлами:
global dir := "C:\2"
Download("http://avatars-fast.yandex.net/get-direct/R85qdm4hRHr-gA65dkojGA/y90")
Download("https://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c")
Download(url) {
If (!InStr(url,"://"))
url := "http://" . url
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
ComObjError(false), WebRequest.Open("GET", url), WebRequest.Send()
If (cdHeader := WebRequest.GetResponseHeader("Content-Disposition"))
RegexMatch(cdHeader, "filename=""(?<name>[^""]+)""", file)
Else
{
SplitPath, url, fileName, , ext
if (ext = "" && ctHeader := WebRequest.GetResponseHeader("Content-Type"))
filename := filename "." SubStr(ctHeader, InStr(ctHeader, "/")+1)
}
StreamToFile(WebRequest.ResponseStream, fileName), WebRequest := ""
}
StreamToFile(Stream, fileName) {
If (ComObjType(Stream) != 0xD)
Return 0
pIStream := ComObjQuery(Stream, "{0000000c-0000-0000-C000-000000000046}")
oFile := FileOpen(dir "\" fileName, "w")
While (cbRead != 0)
VarSetCapacity(Buffer, 8192)
, DllCall(NumGet(NumGet(pIStream + 0) + 3 * A_PtrSize)
, "ptr", pIStream, "ptr", &Buffer, "uint", 8192, "ptr*", cbRead)
, oFile.RawWrite(&Buffer, cbRead)
Return 1, ObjRelease(pIStream), oFile.Close()
}
Только большие файлы качать не хочет.
Например:
Так ссылка http://dl.firedrive.com/?key=MjBBN0M5OU … M4ZDJjY2I= невалидная. У меня инет мобильный, но запустив http://ru.download.nvidia.com/Windows/3 … l-whql.exe - 264 мб, ушло в ожидание, то есть как будто начало качать.
Значит у вас свободной оперативки больше, чем 264 мб.
Попробуйте с этим файлом:
Download("http://www.malcev.lv/DOM/hochu_domoj_18_05_2014.avi")
На оф.форуме предложили более правильный вариант с определением mimeType.
Вместо этого:
if (ext = "" && ctHeader := WebRequest.GetResponseHeader("Content-Type"))
filename := filename "." SubStr(ctHeader, InStr(ctHeader, "/")+1)
Это:
if (ext = "" && ctHeader := WebRequest.GetResponseHeader("Content-Type"))
{
RegRead, ext, HKEY_CLASSES_ROOT, MIME\Database\Content Type\%ctHeader%, Extension
filename := filename ext
}
Инфо можно получить до закачки, HttpQueryInfo(dLocation, 22) аналог WebRequest.getAllResponseHeaders(). Как разобрать Info понятно. Метод присвоения имён можно оставить прежний, я не стал парится. Можно сделать мульти закачку - UrlDownloadToFile качает в другом процессе обновляя сообщениями Progress основного.
На этой ссылке
url = http://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c
скрипт вылетает почему то, остальные работают.
#SingleInstance Force
#MaxThreads 3
SetWorkingDir %A_Desktop%\
; http://www.autohotkey.com/board/topic/103382-need-some-help-with-a-download-progress-bar/
url = http://www.malcev.lv/DOM/hochu_domoj_18_05_2014.avi
Download(url)
Download(dLocation_p)
{
global path, dLocation, FullFileName, FullSize
dLocation = %dLocation_p%
SplitPath, dLocation, path
FullSize := HttpQueryInfo(dLocation, 5)
MsgBox, , % path, % Info := HttpQueryInfo(dLocation, 22)
Progress, H80, , Downloading..., %path% Download
SetTimer, GetSize, 100
UrlDownloadToFile, %dLocation%, %path%
SetTimer, GetSize, -1
Return
}
GetSize:
FileOpen(path, "r")
FileGetSize, FSize, %path%
UpdateSize := Ceil((FSize / FullSize) * 100)
Progress, %UpdateSize%, %UpdateSize%`% Complete, Downloading...
, % Trim(t:=FSize/1000, "0") "kb / " RTrim(t:=FullSize/1000, "0") "kb || " path
Return
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="") {
hModule := DllCall("LoadLibrary", "str", dll := "wininet.dll")
ver := ( A_IsUnicode && !RegExMatch( A_AhkVersion, "\d+\.\d+\.4" ) ? "W" : "A" )
InternetOpen := dll "\InternetOpen" ver
HttpQueryInfo := dll "\HttpQueryInfo" ver
InternetOpenUrl := dll "\InternetOpenUrl" ver
If (Proxy != "")
AccessType=3
Else
AccessType=1
io_hInternet := DllCall( InternetOpen
, "str", ""
, "uint", AccessType
, "str", Proxy
, "str", ProxyBypass
, "uint", 0) ;dwFlags
If (ErrorLevel != 0 or io_hInternet = 0)
{
DllCall("FreeLibrary", "uint", hModule)
return, -1
}
iou_hInternet := DllCall( InternetOpenUrl
, "uint", io_hInternet
, "str", url
, "str", ""
, "uint", 0
, "uint", 0x80000000
, "uint", 0)
If (ErrorLevel != 0 or iou_hInternet = 0)
{
DllCall("FreeLibrary", "uint", hModule)
return, -1
}
VarSetCapacity(buffer, 1024, 0)
VarSetCapacity(buffer_len, 4, 0)
Loop, 5
{
hqi := DllCall( HttpQueryInfo
, "uint", iou_hInternet
, "uint", QueryInfoFlag
, "uint", &buffer
, "uint", &buffer_len
, "uint", 0)
If (hqi = 1) {
hqi=success
break
}
}
IfNotEqual, hqi, success, SetEnv, res, timeout
If (hqi = "success")
{
p := &buffer
Loop
{
l := DllCall("lstrlen", "UInt", p)
VarSetCapacity(tmp_var, l+1, 0)
DllCall("lstrcpy", "Str", tmp_var, "UInt", p)
p += l + 1
res := res . tmp_var
If (*p = 0)
Break
}
}
DllCall("wininet\InternetCloseHandle", "uint", iou_hInternet)
DllCall("wininet\InternetCloseHandle", "uint", io_hInternet)
DllCall("FreeLibrary", "uint", hModule)
return, res
}
Esc::
ExitApp
Ну и в итоге у вас получился скрипт, который скачивает все, кроме файлов со скрытым расширением.
Проверял не только на гугле.
И еще я заметил, что UrlDownloadToFile качает медленнее чем WinHttpRequest.
Ну и в итоге у вас получился скрипт, который скачивает все, кроме файлов со скрытым расширением.
Это ведь качает - http://avatars-fast.yandex.net/get-dire … dkojGA/y90
Метод присвоения имён можно оставить прежний, я не стал парится.
Неужели не очевидно?
И еще я заметил, что UrlDownloadToFile качает медленнее чем WinHttpRequest.
Главное\потому, что не в оперативку.
По той ссылке с гугла в этом цикле происходит ошибка, хотя первые 63 символа инфо определяются, тут надо посвящённым смотреть.
p := &buffer
Loop
{
l := DllCall("lstrlen", "UInt", p)
VarSetCapacity(tmp_var, l+1, 0)
DllCall("lstrcpy", "Str", tmp_var, "UInt", p)
p += l + 1
res := res . tmp_var
If (*p = 0)
Break
}
}
Для начала в AHK_L у поинтеров, как и у хэндлов, тип данных не "UInt", а "Ptr".
l := DllCall("lstrlen", "Ptr", p)
VarSetCapacity(tmp_var, l+1, 0)
DllCall("lstrcpy", "Str", tmp_var, "Ptr", p)
url = https://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c
С этой ссылкой по прежнему вылетает.
Ну, вот так правильно:
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", "str", "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
Error := 1
if !io_hInternet := DllCall("wininet\InternetOpen", "str", "", "uint", AccessType, "str", Proxy, "str", ProxyBypass, "uint", 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, "str", url, "str", "", "uint", 0, "uint", 0x80000000, "uint", 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(&buffer_len+0, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, "uint", QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, "uint", 0)
} Until hqi
Error := ""
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, Error ? -1 : StrGet(&buffer)
}
Только чем это лучше, чем
pWHttp := ComObjCreate("WinHttp.WinHttpRequest.5.1")
pWHttp.Open("GET", "https://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c", False)
pWHttp.Send()
MsgBox, % pWHttp.getAllResponseHeaders()
pWHttp := ""
?
Браво teadrinker! Ещё и короче оригинала.
Только чем это лучше, чем
Как чем, смысл затеи узнать данные файла до его скачивания, особенно если файл большой.
url = http://ru.download.nvidia.com/Windows/335.23/335.23-desktop-win8-win7-winvista-64bit-international-whql.exe
pWHttp := ComObjCreate("WinHttp.WinHttpRequest.5.1")
pWHttp.Open("GET", url, False)
pWHttp.Send()
MsgBox, % pWHttp.getAllResponseHeaders()
pWHttp := ""
url := "http://ru.download.nvidia.com/Windows/335.23/335.23-desktop-win8-win7-winvista-64bit-international-whql.exe"
pWHttp := ComObjCreate("WinHttp.WinHttpRequest.5.1")
pWHttp.Open("GET", url, true)
pWHttp.Send()
Loop
{
if (A_Index = 10 && Error := 1)
break
Sleep, 1000
try if AllResponseHeaders := pWHttp.getAllResponseHeaders()
break
catch
continue
}
pWHttp := ""
MsgBox, % Error ? "Время ожидания истекло" : AllResponseHeaders
Хм... Я делал подобные попытки, но видимо как то не так.
pWHttp.Open("GET", url, true)
А если сервер не особо доступен, и десяти секунд будет мало, разве способ HttpQueryInfo не более "правилен"?
pWHttp.Open("GET", url, true)
Знаю, так и пробовал. В AhkSpy также обновление сделано.
А если сервер не особо доступен, и десяти секунд будет мало, разве способ HttpQueryInfo не более "правилен"?
Тут уже точно к знатокам нужно. Я думаю, что эти два метода почти аналогичны, только в первом случае будет ждать бесконечное/неизвестное время, пока не будет доступна информация. Во втором варианте приемлемое время можно указать явно.
в первом случае будет ждать бесконечное/неизвестное время, пока не будет доступна информация.
Тут уже по вкусам, кому как.
WinHttpRequest хорош asynchronous mode, можно запустить кучу "закачек" (но только в оперативку?), а есть варианты нескольких закачек в файл из одного процесса AutoHotkey ?
Не думаю.
Наверно это стоить поместить в Коллекцию!
А на какую тему, именно определение расширения? Тут есть одна фишка — определение через реестр про типу данных.
url := "http://ru.download.nvidia.com/Windows/335.23/335.23-desktop-win8-win7-winvista-64bit-international-whql.exe"
pWHttp := ComObjCreate("WinHttp.WinHttpRequest.5.1")
pWHttp.Open("GET", url, true)
pWHttp.Send()
Loop
{
if (A_Index = 10 && Error := 1)
break
Sleep, 1000
try if AllResponseHeaders := pWHttp.getAllResponseHeaders()
break
catch
continue
}
pWHttp := ""
MsgBox, % Error ? "Время ожидания истекло" : AllResponseHeaders
Так этим кодом расширение не определяется.
На оф.форуме один форумчанин ответил, что думает что можно как-то качать через httpRequest.ahk так чтобы не перегружался буфер.
Но там в такие дебри лезть надо....
http://www.autohotkey.com/board/topic/6 … /?p=650791
Но это работает только в комплексе, для некоторых ссылок не работает
Download("http://avatars-fast.yandex.net/get-direct/R85qdm4hRHr-gA65dkojGA/y90")
Да и не сильно отличается от того что в Content-Type.
Так этим кодом расширение не определяется.
Так ведь наверное потому что просто нет ничего связанного с разбором инфо, у тебя же уже всё для этого есть. Так вроде всё определяет:
url = https://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c
url = http://ahkscript.org/download/ahk-install.exe
url = http://avatars-fast.yandex.net/get-direct/R85qdm4hRHr-gA65dkojGA/y90
Download(url)
Download(url)
{
Global Path, Location, FullSize, KBSize
Location = %url%
Info := HttpQueryInfo(Location, 22)
RegexMatch(Info, "\RContent-Disposition: .*?filename=""(?<D>.*?)""", C)
If CD !=
Path := CD
Else
{
RegexMatch(Info, "\RContent-Type: .*?/(?<T>.*?)\R", C)
SplitPath, Location, FileName, , Ext, NameNoExt
if (ext = "" && CT != "")
Path := NameNoExt "." CT
Else
Path := FileName
}
RegexMatch(Info, "\RContent-Length: (?<L>.*?)\R", C)
FullSize := CL
MsgBox % Path "`n`n" KBSize := RTrim(t:=FullSize/1000, "0") "kb"
Progress, H80, , Downloading..., %Path% Download
SetTimer, GetSize, 100
UrlDownloadToFile, %Location%, %Path%
SetTimer, GetSize, -1
Return
}
GetSize:
FileOpen(Path, "r")
FileGetSize, FSize, %Path%
UpdateSize := Ceil((FSize / FullSize) * 100)
Progress, %UpdateSize%, %UpdateSize%`% Complete, Downloading...
, % RTrim(t:=FSize/1000, "0") "kb / " KBSize " || " Path
Return
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", "str", "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
Error := 1
if !io_hInternet := DllCall("wininet\InternetOpen", "str", "", "uint", AccessType, "str", Proxy, "str", ProxyBypass, "uint", 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, "str", url, "str", "", "uint", 0, "uint", 0x80000000, "uint", 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(&buffer_len+0, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, "uint", QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, "uint", 0)
} Until hqi
Error := ""
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, Error ? -1 : StrGet(&buffer)
}
Esc::
ExitApp
Табличка 100% Downloading не исчезает после закачки.
Сделай свой прогресс.
Немного переделал прогресс.
По-моему отличное решение получилось.
serzh82saratov и teadrinker огромный РЕСПЕКТ
Апдейт, Баг обнаружил - при несуществующей ссылке он все равно что-то качает либо подвисает.
Надо добавить парсинг на ответ 404 Not Found.
Может как-то так?
Info := HttpQueryInfo(Location, 22)
If (Info ~= "404 Not Found")
msgbox Error
url = http://ahkscript.org/downl45oad/ahk-install1.exe
Download(url)
Download(url)
{
Global Path, Location, FullSize, KBSize
Location = %url%
Info := HttpQueryInfo(Location, 22)
RegexMatch(Info, "\RContent-Disposition: .*?filename=""(?<D>.*?)""", C)
If CD !=
Path := CD
Else
{
RegexMatch(Info, "\RContent-Type: .*?/(?<T>.*?)\R", C)
SplitPath, Location, FileName, , Ext, NameNoExt
if (ext = "" && CT != "")
Path := NameNoExt "." CT
Else
Path := FileName
}
RegexMatch(Info, "\RContent-Length: (?<L>.*?)\R", C)
FullSize := CL
MsgBox % Path "`n`n" KBSize := RTrim(t:=FullSize/1000, "0") "kb"
SetTimer, GetSize, 100
UrlDownloadToFile, %Location%, %Path%
msgbox Done
Return
}
GetSize:
FileOpen(Path, "r")
FileGetSize, FSize, %Path%
UpdateSize := Ceil((FSize / FullSize) * 100)
Progress, %UpdateSize%, %UpdateSize%`% Complete, Downloading...
, % RTrim(t:=FSize/1000, "0") "kb / " KBSize " || " Path
if (UpdateSize = 100)
{
SetTimer, GetSize, off
Progress, off
}
Return
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", "str", "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
Error := 1
if !io_hInternet := DllCall("wininet\InternetOpen", "str", "", "uint", AccessType, "str", Proxy, "str", ProxyBypass, "uint", 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, "str", url, "str", "", "uint", 0, "uint", 0x80000000, "uint", 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(&buffer_len+0, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, "uint", QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, "uint", 0)
} Until hqi
Error := ""
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, Error ? -1 : StrGet(&buffer)
}
Esc::
ExitApp
Вот так вроде работает:
url = http://ahkscript.org/downl45oad/ahk-install1.exe
Download(url)
Download(url)
{
Global Path, Location, FullSize, KBSize
Location = %url%
Info := HttpQueryInfo(Location, 22)
If (Info ~= "404 Not Found")
{
msgbox Error
return
}
RegexMatch(Info, "\RContent-Disposition: .*?filename=""(?<D>.*?)""", C)
If CD !=
Path := CD
Else
{
RegexMatch(Info, "\RContent-Type: .*?/(?<T>.*?)\R", C)
SplitPath, Location, FileName, , Ext, NameNoExt
if (ext = "" && CT != "")
Path := NameNoExt "." CT
Else
Path := FileName
}
RegexMatch(Info, "\RContent-Length: (?<L>.*?)\R", C)
FullSize := CL
MsgBox % Path "`n`n" KBSize := RTrim(t:=FullSize/1000, "0") "kb"
SetTimer, GetSize, 100
UrlDownloadToFile, %Location%, %Path%
msgbox Done
Return
}
GetSize:
FileOpen(Path, "r")
FileGetSize, FSize, %Path%
UpdateSize := Ceil((FSize / FullSize) * 100)
Progress, %UpdateSize%, %UpdateSize%`% Complete, Downloading...
, % RTrim(t:=FSize/1000, "0") "kb / " KBSize " || " Path
if (UpdateSize = 100)
{
SetTimer, GetSize, off
Progress, off
}
Return
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", "str", "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
Error := 1
if !io_hInternet := DllCall("wininet\InternetOpen", "str", "", "uint", AccessType, "str", Proxy, "str", ProxyBypass, "uint", 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, "str", url, "str", "", "uint", 0, "uint", 0x80000000, "uint", 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(&buffer_len+0, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, "uint", QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, "uint", 0)
} Until hqi
Error := ""
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, Error ? -1 : StrGet(&buffer)
}
Esc::
ExitApp
По-моему отличное решение получилось.
Не пойму, зачем там создаётся лишняя переменная?
Location = %url%
Где то так.
url = http://ahkscript.org/download/ahk-install.exe
url = http://ahkscript.org/downl45oad/ahk-install1.exe
MsgBox % Download(url)
Return
Download(Location)
{
Global Path, FullSize, KBSize
Info := HttpQueryInfo(Location, 22)
RegexMatch(Info, ".*? (.*?)\R", stat)
If !InStr(stat1, "200 OK")
Return "Error " stat1
RegexMatch(Info, "\RContent-Disposition: .*?filename=""(?<D>.*?)""", C)
If CD !=
Path := CD
Else
{
RegexMatch(Info, "\RContent-Type: .*?/(?<T>.*?)\R", C)
SplitPath, Location, FileName, , Ext, NameNoExt
if (ext = "" && CT != "")
Path := NameNoExt "." CT
Else
Path := FileName
}
RegexMatch(Info, "\RContent-Length: (?<L>.*?)\R", C)
FullSize := CL
MsgBox % Path "`n`n" KBSize := RTrim(t:=FullSize/1024, "0") "kb"
SetTimer, GetSize, 100
UrlDownloadToFile, %Location%, %Path%
Return "Complete"
}
GetSize:
FileOpen(Path, "r")
FileGetSize, FSize, %Path%
UpdateSize := Ceil((FSize / FullSize) * 100)
Progress, %UpdateSize%, %UpdateSize%`% Complete, Downloading...
, % RTrim(t:=FSize/1024, "0") "kb / " KBSize " || " Path
if (UpdateSize = 100)
{
SetTimer, GetSize, off
Progress, off
}
Return
RegexMatch(Info, "\RContent-Disposition: .*?filename=""(?<D>.*?)""", C)
Regex неверный, по-моему. Разве есть гарантия, что Content-Disposition не будет первой строчкой?
MsgBox % Path "`n`n" KBSize := RTrim(t:=FullSize/1000, "0") "kb"
Сколько байтов в килобайте, по-твоему?
Regex неверный, по-моему. Разве есть гарантия, что Content-Disposition не будет первой строчкой?
Там первой строкой всегда статус:
HTTP/1.1 200 OK
Сколько байтов в килобайте, по-твоему?
Переделал, всё осталось с забугорного оригинала. Но теперь циферки не красивые.
Но теперь циферки не красивые.
А что мешает округлить до определённого знака?
Обозначение килобайта — KB или КБ, а "kb" можно с килобитами перепутать.
url = http://ahkscript.org/download/ahk-install.exe
MsgBox % Download(url)
Return
Download(Location)
{
Global Path, FullSize, KBSize
Info := HttpQueryInfo(Location, 22)
RegexMatch(Info, ".*? (.*?)\R", stat)
If !InStr(stat1, "200 OK")
Return "Error: " stat1
RegexMatch(Info, "\RContent-Disposition: .*?filename=""(?<D>.*?)""", C)
If CD !=
Path := CD
Else
{
SplitPath, Location, FileName, , Ext, NameNoExt
RegexMatch(Info, "\RContent-Type: (.*?/(.*?))\R", CT)
RegRead, ExtMIME, HKEY_CLASSES_ROOT, MIME\Database\Content Type\%CT1%, Extension
If (ExtMIME != "")
Path := NameNoExt ExtMIME
Else If (Ext = "" && CT2 != "")
Path := NameNoExt "." CT2
Else
Path := FileName
}
If !Path
Return "Error: Path not found"
RegexMatch(Info, "\RContent-Length: (?<L>.*?)\R", C), FullSize := CL
MsgBox % Path "`n`n" KBSize := Floor(FullSize/1024) "KB"
SetTimer, GetSize, 100
UrlDownloadToFile, %Location%, %Path%
SetTimer, GetSize, -1
Progress, Hide
Return "Complete"
}
GetSize:
FSize := FileOpen(Path, "r").Length
Percent := Floor((FSize / FullSize) * 100)
Progress, %Percent%, %Percent%`% Complete, Downloading...
, % Floor(FSize/1024) "KB / " KBSize " || " Path
Return
Esc::
ExitApp
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", "str", "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
Error := 1
if !io_hInternet := DllCall("wininet\InternetOpen", "str", "", "uint", AccessType, "str", Proxy, "str", ProxyBypass, "uint", 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, "str", url, "str", "", "uint", 0, "uint", 0x80000000, "uint", 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(&buffer_len+0, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, "uint", QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, "uint", 0)
} Until hqi
Error := ""
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, Error ? -1 : StrGet(&buffer)
}
А почему перед
Else
Path := FileName
не использована возможность определения расширения через реестр?
Можно еще добавить запрет перезаписи файла.
SplitPath, Path, FileName, Dir, Ext, NameNoExt
n =
loop
{
Path := Dir "\" nameNoExt n "." ext
ifNotExist, %Path%
break
n++
}
UrlDownloadToFile, %Location%, %Path%
не использована возможность определения расширения через реестр?
Поправил.
Percent := Ceil((FSize / FullSize) * 100)
Почему здесь Ceil()? значение 99.1 будет равно 100, что неправильно. Тут нужно Floor().
Поправил 44й, выложил полный вариант.
Можно теперь и в коллекцию? Как я понял аналогов такого на AHK нету.
Хороший скрипт для коллекции, но, как мне кажется, для полноценной работы он должен уметь обрабатывать следующие ситуации:
- файл с таким названием уже есть. Можно вторым параметром передать в Download(Location) флаг, как вести в таком случае - заменить старый файл, переименовать его, переименовать новый, отменить закачку или спросить пользователя;
- файл существует и заблокирован для записи другим процессом;
- у пользователя недостаточно прав для записи в папку Location;
- такой папки вообще нет.
Список можно расширить, но эти ситуации достаточно часто встречаются и на их обработку нужно обратить внимание в первую очередь.
Поддерживаю. Про недостаточно прав ничего не знаю. Как это проверить?
Небольшое исправление:
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", Str, "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
if !io_hInternet := DllCall("wininet\InternetOpen", Str, "", UInt, AccessType, Str, Proxy, Str, ProxyBypass, UInt, 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, Str, url, Str, "", UInt, 0, UInt, 0x80000000, UInt, 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(buffer_len, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, UInt, QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, UInt, 0)
} Until hqi
success := 1
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, success ? StrGet(&buffer) : -1
}
Один success вместо двух Error.
Поддерживаю. Про недостаточно прав ничего не знаю. Как это проверить?
Наверно при помощи команды FileGetAttrib.
А как конкретно?
Например, так:
FileGetAttrib, Attributes, C:\WINDOWS
MsgBox, %Attributes%
The string returned will contain a subset of the letters in the string "RASHNDOCT":
R = READONLY
A = ARCHIVE
S = SYSTEM
H = HIDDEN
N = NORMAL
D = DIRECTORY
O = OFFLINE
C = COMPRESSED
T = TEMPORARY
То есть, как я понял, Attributes = R, когда недостаточно прав для записи.
Нет, READONLY — это когда в свойствах папки стоит флажок "только для чтения", с правами это никак не связано вроде.
Это связано с правами доступа в ntfs. Например, пользователь без привилегий администратора попытается записать файл в папку windows.
Может FileOpen(FileName, "w") и смотреть A_LastError?
Ещё один способ закачки с прогрессом, так понимаю к нескольким закачкам из одного скрипта, тоже не имеет отношения.
http://www.autohotkey.com/board/topic/1 … ntry174581
DetectHiddenWindows, On
url = http://ru.download.nvidia.com/Windows/335.23/335.23-desktop-win8-win7-winvista-64bit-international-whql.exe
url = http://ahkscript.org/download/ahk-install.exe
splitpath,url,ofn
file := A_Desktop "\" ofn
MsgBox, % file "`n" url
If Download( url, file )
MsgBox Ok
Else
MsgBox Error
Return
Download( url, file ) {
static _init
global _cu
Splitpath,file, _dFile
if ! init
{
RegRead,SysNot,HKCU,AppEvents\Schemes\Apps\.Default\SystemNotification\.Current
Transform, SysNot, deref, %sysnot%
SysGet, m, MonitorWorkArea, 1
y:=(mBottom-52-2),x:=(mRight-330-2),init:=1,VarSetCapacity(vt,4*11),nPar:="31132253353"
Loop, Parse, nPar
NumPut(RegisterCallback("DL_Progress","Fast",A_LoopField,A_Index-1),vt,4*(A_Index-1))
}
VarSetCapacity(_cu,255),DllCall("shlwapi\PathCompactPathExW", "Str", _cu, "Str", url, "UInt", 50)
Progress,Hide CWFAFAF7 CT000020 CB445566 x%x% y%y% w330 h52 B1 FS8 WM700 WS700 FM8 ZH12 ZY3 C11,,%_cu%,AutoHotkeyProgress,Tahoma
WinSet, Transparent,180, AutoHotkeyProgress
SoundPlay, %SysNot%
re := DllCall("urlmon\URLDownloadToFileW", "Ptr", 0, "Str", url, "Str", file, "Uint", 0, "UintP", &vt)
SoundPlay, %SysNot%
Progress, Off
Return re=0 ? 1 : 0
}
DL_Progress( pthis, nP=0, nPMax=0, nSC=0, pST=0 ) {
global _cu
If (A_EventInfo=6)
{
Progress, Show
Progress, % (P:=100*nP//nPMax),% "Downloading: " Round(np/1024,1) " Kb / "
. Round(npmax/1024) " Kb [ " p "`% ]",%_cu%
}
Return 0
}
Про этот параметр не до конца понял:
pCaller
A pointer to the controlling IUnknown interface of the calling ActiveX component, if the caller is an ActiveX component. If the calling application is not an ActiveX component, this value can be set to NULL. Otherwise, the caller is a COM object that is contained in another component, such as an ActiveX control in the context of an HTML page. This parameter represents the outermost IUnknown of the calling component. The function attempts the download in the context of the ActiveX client framework, and allows the caller container to receive callbacks on the progress of the download.
У меня этот код не работает. Обрати внимание на дату поста — 2008 г., написано под AHK-basic.
Это связано с правами доступа в ntfs. Например, пользователь без привилегий администратора попытается записать файл в папку windows.
Не совсем понял, если права доступа есть, этот атрибут можно просто снять (так же, как и поставить).
У меня этот код не работает. Обрати внимание на дату поста — 2008 г., написано под AHK-basic.
Чутка поправил.
Ну у меня же работает, под анкх64 может не допилено.
Не совсем понял, если права доступа есть, этот атрибут можно просто снять (так же, как и поставить).
По-моему, мы говорим про немного разные вещи. Смена атрибутов файла (R/O или R/W) ничего не даст, если в файловой системе не прописаны разрешения доступа. Даже запуск скрипта от имени администратора не поможет, если в перечне групп и пользователей убрать администраторов.
Пока не вижу решения, как силами AHK сменять действующие разрешения для файлов и папок, да и нужно ли это. На мой взгляд, самым простым способом будет, как предложил serzh82saratov в #58, открыть файл для записи и проверять код ошибки. Только сразу уж так "рубить с плеча не стоит" с параметром "w" , может пользователю не хочется перезаписывать существующий файл - параметр "a" подойдет и для создания, и файл не удалит. А дальше уже можно действовать по своему сценарию.
Не даёт мне покоя #59. Какое то подозрение, про 1 параметр. Если прописать как то некий ActiveX component, то может и асинхрон нарисуется... Не говоря уже про, по моему мнению, более правильный прогресс закачки.
Сабж интересен, но хочется увидеть в итоге полноценную качалку, несколько закачек с одного скрипта, пускай для начала, с созданием для каждой, своего процесса.
Irbis в #51 вызвался, пущай и запостит первенца в коллекцию, а Мы уже чем сможем.
Я только завтра смогу посмотреть, сейчас без компьютера.
A pointer to the controlling IUnknown interface of the calling ActiveX component, if the caller is an ActiveX component. If the calling application is not an ActiveX component, this value can be set to NULL.
Адрес управляющего IUnknown-интерфейса вызывающего ActiveX-компонента, если вызывающий объект является ActiveX-компонентом. Если вызывающее приложение не является ActiveX-компонентом, это значение должно быть NULL.
AHK-скрипт не является ActiveX-компонентом, поэтому ничего другого здесь прописать нельзя.
Irbis в #51 вызвался, пущай и запостит первенца в коллекцию, а Мы уже чем сможем.
Мне кажется, это будет несправедливо, моего кода в данном случае нет ни строчки... Так, пара идей только, и те пока не реализованы.
Исправленный 44-ый пост.
Убрал чувствительность к регистру при парсинге инфо от сервера.
url = http://ahkscript.org/download/ahk-install.exe
MsgBox % Download(url)
Return
Download(Location)
{
Global Path, FullSize, KBSize
Info := HttpQueryInfo(Location, 22)
RegexMatch(Info, "i).*? (.*?)\R", stat)
If !InStr(stat1, "200 OK")
Return "Error: " stat1
RegexMatch(Info, "i)\RContent-Disposition: .*?filename=""(?<D>.*?)""", C)
If CD !=
Path := CD
Else
{
SplitPath, Location, FileName, , Ext, NameNoExt
RegexMatch(Info, "i)\RContent-Type: (.*?/(.*?))\R", CT)
RegRead, ExtMIME, HKEY_CLASSES_ROOT, MIME\Database\Content Type\%CT1%, Extension
If (ExtMIME != "")
Path := NameNoExt ExtMIME
Else If (Ext = "" && CT2 != "")
Path := NameNoExt "." CT2
Else
Path := FileName
}
If !Path
Return "Error: Path not found"
RegexMatch(Info, "i)\RContent-Length: (?<L>.*?)\R", C), FullSize := CL
MsgBox % Path "`n`n" KBSize := Floor(FullSize/1024) "KB"
SetTimer, GetSize, 100
UrlDownloadToFile, %Location%, %Path%
SetTimer, GetSize, -1
Progress, Hide
Return "Complete"
}
GetSize:
FSize := FileOpen(Path, "r").Length
Percent := Floor((FSize / FullSize) * 100)
Progress, %Percent%, %Percent%`% Complete, Downloading...
, % Floor(FSize/1024) "KB / " KBSize " || " Path
Return
Esc::
ExitApp
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", "str", "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
Error := 1
if !io_hInternet := DllCall("wininet\InternetOpen", "str", "", "uint", AccessType, "str", Proxy, "str", ProxyBypass, "uint", 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, "str", url, "str", "", "uint", 0, "uint", 0x80000000, "uint", 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(&buffer_len+0, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, "uint", QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, "uint", 0)
} Until hqi
Error := ""
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, Error ? -1 : StrGet(&buffer)
}
Тут надо бы регексы заменить на GetResponseHeader для надёжности, и HttpQueryInfo заменить на HEAD запрос как здесь http://forum.script-coding.com/viewtopi … 653#p83653 для упрощения. Там же и закачка частями, таймер проверки размера файла в этом случае не требуется. Получение имени файла выведи в отдельную функцию для наглядности дальнейших редакций. Будет достаточно времени, добавлю мульти закачку.
А чем сейчас этот скрипт ненадежен?
Чем другой вариант лучше?
HttpQueryInfo заменить на HEAD запрос
Я поспешил, в случае такой ссылки:
url = https://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c
в HEAD запросе совсем не то что нужно.
oWHR.Option(6) := 0
и редиректы тут не помогают. Так что оставляем как есть.
Можно с помощью GET получить нужные заголовки, скачав 1 байт. Размер можно извлечь из Content-Range.
url = https://docs.google.com/uc?export=download&id=0B7FildjsrNkILWhYVHYwanJLS3c
HTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")
HTTP.Open("GET", url)
HTTP.SetRequestHeader("Range", "bytes=0-0")
HTTP.Send()
MsgBox, % HTTP.GetAllResponseHeaders()
YMP
Чертовски любопытно!
Диапазон можно обозначать и от конца файла. Вот так последний байт можно скачать:
HTTP.SetRequestHeader("Range", "bytes=-1")
Если сервер не поддерживает диапазоны, то, как я понимаю, в свойстве Status должен быть код ошибки. Но размер файла в таком случае остаётся неизвестным. Вряд ли в заголовках он будет обозначен.
И в таком случае опять же пользовать HttpQueryInfo? Тогда уже смысл этого метода теряется.
Вопрос в том, как HttpQueryInfo получает эти заголовки. Как ещё, если не отправляя какой-то запрос? А если так, то что мешает сделать то же объектом HTTP? Запрос HEAD, как мы видим, не годится. Может, она использует GET так же, как я. Надо бы найти сервер без поддержки диапазонов и проверить на нём работу HttpQueryInfo. Иначе откуда уверенность, что она там сработает?
Хотя да, думаю, она может просто остановить приём данных после получения заголовков.
Кажется с github любой файл, уточнить с телефона не могу.
Апдейт мессаджа не видел. .Значит всё таки по вашему как...
Хотя да, думаю, она может просто остановить приём данных после получения заголовков.
Насколько помню, в этих случаях оно качает файл целиком. Если речь про гет запрос, без возможности сервера отдавать диапазонами.
Насколько помню, в этих случаях оно качает файл целиком. Если речь про гет запрос, без возможности сервера отдавать диапазонами.
HttpQueryInfo вполне может и не качать. Как только скачались заголовки, функция может прекратить приём данных, т.к. ей больше ничего не нужно.
А чем HttpQueryInfo не устраивает?
В чем его минусы?
Да всем устраивает, просто рассуждения о более коротком коде.
Разбираемся, как что работает, какие есть возможности.
HttpQueryInfo - это аналог:
url = https://www.autohotkey.com/download/AutoHotkeyInstall.exe
req := ComObjCreate("MSXML2.XMLHTTP.6.0")
req.Open("GET", url, true)
req.send()
while req.readyState <2 ; HEADERS_RECEIVED
sleep 10
msgbox % req.GetAllResponseHeaders()
С Microsoft.XMLHTTP, Msxml2.XMLHTTP, Msxml2.XMLHTTP.3.0, WinHttpRequest такого провернуть не получится.
Ну и непонятно, почему мы считали, что после отправки запроса на сервер и после получения заголовков придется ждать получение тела ответа.
url = https://www.autohotkey.com/download/AutoHotkeyInstall.exe
req := ComObjCreate("WinHttp.WinHttpRequest.5.1")
a := a_tickcount
req.Open("GET", url)
req.send()
req.GetAllResponseHeaders()
msgbox % a_tickcount - a
a := a_tickcount
req.ResponseBody
msgbox % a_tickcount - a
Размер надёжней получать через MaxIndex().
url := "https://www.dropbox.com/sh/j1msw4e8dup2c5q/AAANYUWXcyBDgxVGkveU7AFla?dl=1"
;url := "https://raw.githubusercontent.com/f5devcentral/f5-irule-editor/master/iRuler/Templates/Blank.txt" ;1 byte
;url := "https://raw.githubusercontent.com/SparkPost/java-sparkpost/master/src/main/resources/empty.txt" ;0 bytes
req := ComObjCreate("WinHttp.WinHttpRequest.5.1")
req.Open("GET", url)
req.send()
msgbox % req.getallresponseheaders()
Body := req.ResponseBody
if IsObject(Body)
length := Body.MaxIndex() + 1
else
length := 0
msgbox % length
Скачать используя буфер (не напрямую в память) можно либо, с ком объектами WinHttpRequest, XMLHTTP с использованием Range, что не везде поддерживается,
либо через WinInet, что и делает UrlDownloadToFile:
https://docs.microsoft.com/en-us/window … etreadfile
либо WinHttp:
https://docs.microsoft.com/en-us/window … tpreaddata
либо Urlmon:
https://docs.microsoft.com/en-us/previo … v%3dvs.85)
Небольшое исправление:
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="") { hModule := DllCall("LoadLibrary", Str, "wininet.dll", Ptr) AccessType := Proxy = "" ? 1 : 3 Loop 1 { if !io_hInternet := DllCall("wininet\InternetOpen", Str, "", UInt, AccessType, Str, Proxy, Str, ProxyBypass, UInt, 0, Ptr) ;dwFlags break if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, Str, url, Str, "", UInt, 0, UInt, 0x80000000, UInt, 0) break VarSetCapacity(buffer_len, 4, 0) Loop { if A_Index = 3 break 2 VarSetCapacity(buffer, NumGet(buffer_len, "UInt")) hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, UInt, QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, UInt, 0) } Until hqi success := 1 } DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet) DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet) DllCall("FreeLibrary", Ptr, hModule) Return, success ? StrGet(&buffer) : -1 }
Один success вместо двух Error.
Тут ошибка:
link := "https://www.google.com/maps/vt/pb=!1m5!1m4!1i12!2i4645!3i2509!4i128!2m2!1e1!3i810!3m9!2sru!3slv!5e1105!12m1!1e4!12m1!1e47!12m1!1e3!4e0!5m1!1e0!23i4111425!23i1358757!23i1358902"
msgbox % HttpQueryInfo(link)
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", Str, "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
if !io_hInternet := DllCall("wininet\InternetOpen", Str, "", UInt, AccessType, Str, Proxy, Str, ProxyBypass, UInt, 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, Str, url, Str, "", UInt, 0, UInt, 0x80000000, UInt, 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(buffer_len, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, UInt, QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, UInt, 0)
} Until hqi
success := 1
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, success ? StrGet(&buffer) : -1
}
Чтобы такого избежать нужно указывать lpszAgent в InternetOpen запросе:
link := "https://www.google.com/maps/vt/pb=!1m5!1m4!1i12!2i4645!3i2509!4i128!2m2!1e1!3i810!3m9!2sru!3slv!5e1105!12m1!1e4!12m1!1e47!12m1!1e3!4e0!5m1!1e0!23i4111425!23i1358757!23i1358902"
msgbox % HttpQueryInfo(link)
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="")
{
hModule := DllCall("LoadLibrary", Str, "wininet.dll", Ptr)
AccessType := Proxy = "" ? 1 : 3
Loop 1
{
if !io_hInternet := DllCall("wininet\InternetOpen", Str, "autohotkey", UInt, AccessType, Str, Proxy, Str, ProxyBypass, UInt, 0, Ptr) ;dwFlags
break
if !iou_hInternet := DllCall("wininet\InternetOpenUrl", Ptr, io_hInternet, Str, url, Str, "", UInt, 0, UInt, 0x80000000, UInt, 0)
break
VarSetCapacity(buffer_len, 4, 0)
Loop
{
if A_Index = 3
break 2
VarSetCapacity(buffer, NumGet(buffer_len, "UInt"))
hqi := DllCall("wininet\HttpQueryInfo", Ptr, iou_hInternet, UInt, QueryInfoFlag, Ptr, &buffer, Ptr, &buffer_len, UInt, 0)
} Until hqi
success := 1
}
DllCall("wininet\InternetCloseHandle", Ptr, iou_hInternet)
DllCall("wininet\InternetCloseHandle", Ptr, io_hInternet)
DllCall("FreeLibrary", Ptr, hModule)
Return, success ? StrGet(&buffer) : -1
}
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться