2015-02-02 6 views
1

Существует множество статей о том, как загрузить файл с помощью WinInet (откуда я получил код), но все они кажутся старше и/или закрыты. Загрузка без имени пользователя и пароля, работает нормально, но если я защитить папку (используя VodaHost) с именем пользователя и паролем, которые я получаю сообщение об ошибке аутентификации при попытке загрузить файл:Delphi Загрузить файл с WinInet с именем пользователя и паролем

401 Несанкционированное ......

Если я получаю доступ через веб-браузер, открывается диалоговое окно имени пользователя и пароля, и я могу получить все в порядке. Папка защищаемой:

http://www.mywebsite.com/downloads

Я установил сервера на: www.mywebsite.com и URL для http://www.mywebsite.com/downloads. Имя пользователя и пароль были подтверждены с помощью веб-браузера.

Я также пробовал много перестановок, и я немного расстроен. Единственное, о чем я могу думать, это то, что это потому, что сервер не защищен, а папка на сервере. Сервер не может быть защищен, так как он будет/будет общедоступным. Если вам нужна дополнительная информация, просто дайте мне знать.

У кого-нибудь есть идеи?

function Download(Server, Url, User, Pass, FileName : string): boolean; 
const 
    BUFFERSIZE = 4096; 

var 
    hSession: HINTERNET; 
    hService: HINTERNET; 
    hHTTP: HINTERNET; 
    lpBuffer: array[0..BufferSize + 1] of Byte; 
    BufferLength: DWORD; 
    dwBytesRead: DWORD; 
    dwSizeOfRq, Reserved, dwByteToRead: DWORD; 
    localFile: file; 
    fsize: DWORD; 

begin 
    try 
    try 
     // Downloads file at URL bypassing cache 
     Result := False; 

     // Initialize the Win32 Internet functions 
     hSession := InternetOpen(PChar('Empyrean'), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ; 
     // See if the session handle is valid 
     if hSession = nil then 
     Exit; 

     hHTTP := InternetConnect(hSession, PChar(Server), INTERNET_DEFAULT_HTTP_PORT, PChar(User), PChar(Pass), INTERNET_SERVICE_HTTP, 0, 0); 
     if hHTTP = nil then 
     Exit; 

     // InternetOpenUrl opens a handle to the Internet file using a URL. The flags indicate that the file will always 
     // be read from the Internet rather than the cache 
     //hService := InternetOpenUrl(hSession, pChar(url), nil, 0, INTERNET_FLAG_DONT_CACHE or INTERNET_FLAG_PRAGMA_NOCACHE or INTERNET_FLAG_RELOAD, 0); 
     hService := InternetOpenUrl(hSession, pChar(url), nil, 0, INTERNET_FLAG_RELOAD, 0); 

     // See if the session handle is valid 
     if hService = nil then 
     begin 
     InternetCloseHandle(hService); 
     Exit; 
     end; 

     HttpQueryInfo(hService, HTTP_QUERY_STATUS_CODE or HTTP_QUERY_FLAG_NUMBER, @dwByteToRead, dwSizeOfRq, Reserved); 
     AssignFile(localFile, FileName); 
     {$I-} 
     Rewrite(localFile, 1); 
    {$I+} 
    if IOResult <> 0 then 
     begin 
     ShowMessage('Cannot create local file: ' + FileName); 
     InternetCloseHandle(hService); 
     Exit; 
     end; 
     BufferLength := BUFFERSIZE; 

     // These three variables will store the size of the file, the size of the HttpQueryInfo content, and the number of bytes read in 
     // total. Now determine the length of a file in bytes 
     dwByteToRead := 0; 
     dwSizeOfRq := 4; // BufferLength 
     Reserved := 0; 

     // get the file's size. 
     if not HttpQueryInfo(hService, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER, @dwByteToRead, dwSizeOfRq, Reserved) then 
     dwByteToRead := 0; 
     FSize := 0; 
     BufferLength := BUFFERSIZE; 

     while (BufferLength > 0) do 
     begin 
     // Read data from the hService handle 
     if not InternetReadFile(hService, @lpBuffer, BUFFERSIZE, BufferLength) then 
      Break; 
     if (BufferLength > 0) and (BufferLength <= BUFFERSIZE) then 
      BlockWrite(localFile, lpBuffer, BufferLength); 
     fsize := fsize + BufferLength; 

     // Check the size of the remaining data. If it is zero, break 
     if BufferLength > 0 then 
      Result := True; 
     end; 

     CloseFile(localFile); 
     Result := True; 
    except 

    end; 
    finally 
    // Close the Internet handle that the application has opened 
    InternetCloseHandle(hService); 
    InternetCloseHandle(hSession); 
    InternetCloseHandle(hHTTP); 
    end; 

end; 
+0

Попробуйте использовать инструмент, как Wireshark сравнивать сетевой трафик, генерируемый из запроса браузера с трафиком, генерируемым вашей программой. Или посмотрите на журналы сервера, если они у вас есть. Как только вы поймете, что изменилось, у вас будет некоторое представление о том, что вы делаете неправильно. –

+1

Пробовали ли вы читать [Документацию MSDN] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa384220%28v=vs.85%29.aspx)? – RRUZ

+0

Пробовал и то и другое, и я не вижу, где я ошибаюсь, т.е. Я не вижу ни того места, где передаются имя пользователя и пароль. Я вижу 401 Несанкционированную линию. Это в значительной степени связано с моей неопытности в использовании WireShark и обзором журналов сервера. – user3698371

ответ

1

Используйте InternetSetOption() указать INTERNET_OPTION_USERNAME и INTERNET_OPTION_PASSWORD значения для ручки возвращенного InternetConnect() перед вызовом InternetOpenUrl().

Прочитайте документацию для получения более подробной информации:

Handling Authentication

В частности:

The InternetOpenUrl and HttpSendRequest functions complete successfully even when authentication is required. The difference is, the data returned in the header files and InternetReadFile would receive an HTML page informing the user of the status code.

Так что если InternetOpenUrl() является "успешной", вы должны будете использовать HttpQueryInfo(), чтобы получить код статуса, и если он равен 401, тогда укажите имя пользователя/пароль (при необходимости попросите пользователя) и повторите попытку. В приведенной выше документации есть пример. Ответ дает вам фактический файл, запрошенный, только если код состояния равен 200.

+0

LebeauThanks, я положил это (и сделал это снова) с той же неуправляемой ошибкой 401: 'InternetSetOption (hHTTP, INTERNET_OPTION_PASSWORD, pChar (Pass), Length (Pass)); InternetSetOption (hHTTP, INTERNET_OPTION_USERNAME, pChar (Пользователь), Длина (Пользователь)); ' – user3698371

+0

@RRUZ Да, но я не эксперт. Я подумал: «То, что я сделал, было правильным, очевидно, нет. – user3698371

+0

@David Heffernan Я думал, и я мог ошибаться, что INTERNET_OPTION_PASSWORD/USERNAME сообщает системе, что я буду передавать строки с именем пользователя и паролем. Это не в показанном коде, но я попробовал его и с тех пор попробовал его снова, как предложил Реми, но безрезультатно. – user3698371

1

Спасибо всем за советы. Теперь у меня есть код работает, включив имя пользователя/пароль в URL:

Server := 'www.myServer.com'; 
URL := 'http://user:[email protected]/downloads/filetodownload'; 

 Смежные вопросы

  • Нет связанных вопросов^_^