VBA WinHTTP для загрузки файла с защищенного паролем https-сайта

Я пытаюсь сохранить файл с https-сайта, защищенного паролем, с помощью WinHTTP. Вот код:

Sub SaveFileFromURL()

Dim FileNum As Long
Dim FileData() As Byte
Dim WHTTP As Object

fileUrl = "https://www.website.com/dir1/dir2/file.xls"
filePath = "C:\myfile.xls"

myuser = "username"
mypass = "password"

Set WHTTP = CreateObject("WinHTTP.WinHTTPrequest.5.1")

WHTTP.Open "GET", fileUrl, False
WHTTP.SetCredentials myuser, mypass, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER
WHTTP.Send

FileData = WHTTP.ResponseBody
Set WHTTP = Nothing

FileNum = FreeFile
Open filePath For Binary Access Write As #FileNum
    Put #FileNum, 1, FileData
Close #FileNum

MsgBox "File has been saved!", vbInformation, "Success"

End Sub

Проблема с аутентификацией. Файл сохраняется, но когда я открываю его в Excel, это просто html-страница входа в систему, а не сам файл. Если я копирую прямой URL-адрес файла и вставляю его в адресную строку браузера, и я не вошел на веб-страницу, эффект будет таким же. Мне представлена ​​страница входа в систему. Затем, если я введу свой логин и пароль, появится окно загрузки, позволяющее мне сохранить файл.

Поэтому я думаю, что часть кода SetCredentials не работает должным образом, потому что если я отлаживаю. Print WHTTP.ResponseBody, это html-код вместо фактических данных файла.

Есть ли способ передать идентификатор пользователя и пароль в WinHTTP, чтобы я мог правильно сохранить файл?

Вот адрес страницы:

https://sst.msde.state.md.us/

======================= РЕДАКТИРОВАТЬ: ========================

Итак, я немного поиграл с этим сегодня и думаю, что двигаюсь вперед. Вот что у меня получилось. Я изменил код следующим образом:

Sub SaveFileFromURL()

Dim FileNum As Long
Dim FileData() As Byte
Dim WHTTP As Object

fileUrl = "https://www.website.com/dir1/dir2/file.xls"
filePath = "C:\myfile.xls"

myuser = "username"
mypass = "password"

strAuthenticate = "start-url=%2F&user=" & myuser & "&password=" & mypass & "&switch=Log+In"

Set WHTTP = CreateObject("WinHTTP.WinHTTPrequest.5.1")

WHTTP.Open "POST", fileUrl, False
WHTTP.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
WHTTP.Send strAuthenticate

WHTTP.Open "GET", fileUrl, False
WHTTP.Send

Debug.Print WHTTP.GetAllResponseHeaders()

FileData = WHTTP.ResponseBody
Set WHTTP = Nothing

FileNum = FreeFile
Open filePath For Binary Access Write As #FileNum
    Put #FileNum, 1, FileData
Close #FileNum

MsgBox "File has been saved!", vbInformation, "Success"

End Sub

Когда я Debug.Print WHTTP.GetAllResponseHeaders (), я получаю, например:

Accept-Ranges: bytes
Content-Disposition: attachement; filename="xxx"
Content-Length: xxxxxx
Content-Type: application/octet-stream

Итак, я думаю, что аутентификация сработала, но я все еще не могу сохранить файл. Когда я продолжу:

FileData = WHTTP.ResponseBody
Set WHTTP = Nothing

FileNum = FreeFile
Open filePath For Binary Access Write As #FileNum
    Put #FileNum, 1, FileData
Close #FileNum

Содержимым сохраненного файла является сама html-страница, но не сам файл.

Я выполнил проверку подлинности правильно, и проблема заключается в сохранении файла на диск, или все еще существует проблема с проверкой подлинности, и поэтому я не могу ее сохранить? Какие-нибудь подсказки?


person user2267971    schedule 26.02.2014    source источник
comment
SetCredentials не кажется очень надежным. Вместо этого вы можете использовать метод POST / GET.   -  person David Zemens    schedule 27.02.2014
comment
Использовать метод POST / GET где / как? Я использую его в своем коде непосредственно перед установкой учетных данных, но он не работает. Есть предложения?   -  person user2267971    schedule 27.02.2014
comment
@ user2267971 Этот ответ: stackoverflow.com/questions/891427/ может быть полезным. Кроме того, вы можете автоматизировать страницу входа в систему через IE, отправить свой идентификатор пользователя и пароль, а затем перейти на страницу, чтобы получить необходимую информацию.   -  person MattB    schedule 27.02.2014
comment
Я уже автоматизировал вход в систему, чтобы получить прямые URL-адреса файлов. Но я хочу иметь возможность загружать файл в автоматическом режиме, без всплывающих окон загрузки. Получение WHTTP.ResponseBody отлично подходит для других незащищенных паролем сайтов, а также для некоторых защищенных паролем сайтов http. Проблема в этом конкретном сайте https. И, кстати, я должен использовать IE для этого.   -  person user2267971    schedule 27.02.2014
comment
Изменить: глядя на html-код веб-сайта, который я предоставил, можно ли выяснить, какой метод необходимо использовать для передачи имени пользователя и пароля и правильной загрузки файла?   -  person user2267971    schedule 27.02.2014
comment
Если вы используете браузер Chrome, вы должны иметь возможность использовать инструменты разработчика для проверки запроса POST, когда вы вручную отправляете учетные данные. Это должно помочь вам структурировать запрос POST в VBA, который воспроизводит способ отправки запроса вашим браузером (IE).   -  person David Zemens    schedule 27.02.2014
comment
Хорошо, я отредактировал свой основной пост, потому что думаю, что сегодня у нас есть прогресс. Есть новые предложения?   -  person user2267971    schedule 27.02.2014


Ответы (1)


Хорошо, я сделал это. Вот код:

Sub SaveFileFromURL()

Dim FileNum As Long
Dim FileData() As Byte
Dim WHTTP As Object

mainUrl = "https://www.website.com/"
fileUrl = "https://www.website.com/dir1/dir2/file.xls"
filePath = "C:\myfile.xls"

myuser = "username"
mypass = "password"

'@David Zemens, I got this by examining webpage code using Chrome, thanks!
strAuthenticate = "start-url=%2F&user=" & myuser & "&password=" & mypass & "&switch=Log+In"

Set WHTTP = CreateObject("WinHTTP.WinHTTPrequest.5.1")

'I figured out that you have to POST authentication string to the main website address not to the direct file address
WHTTP.Open "POST", mainUrl, False 'WHTTP.Open "POST", fileUrl, False
WHTTP.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
WHTTP.Send strAuthenticate

'Then you have to GET direct file url
WHTTP.Open "GET", fileUrl, False
WHTTP.Send

FileData = WHTTP.ResponseBody
Set WHTTP = Nothing

'Save the file
FileNum = FreeFile
Open filePath For Binary Access Write As #FileNum
    Put #FileNum, 1, FileData
Close #FileNum

MsgBox "File has been saved!", vbInformation, "Success"

End Sub

Спасибо за вашу помощь.

Кстати, я нашел эти сообщения очень полезными:

http://www.mrexcel.com/forum/excel-questions/353006-download-file-excel.html.

Как построчно анализировать ответ WinHTTP : CSV в кодировке UTF-8?

person user2267971    schedule 01.03.2014