2010-02-11 19 views
9

Tôi có nhiệm vụ sau: tải xuống tệp bằng HTTPS và xác thực. Indy dường như là con đường để đi nhưng vì một lý do nào đó nó không hoạt động cho đến nay. Tôi đã sau tại chỗ:Cách tải xuống tệp qua HTTPS bằng Indy 10 và OpenSSL?

  • một thành phần TIdHTTP mà tôi sử dụng để tải về
  • một thành phần TIdURI sử dụng để tạo ra các URL
  • một thành phần TIdSSLIOHandlerSocketOpenSSL mà nên cung cấp các kết nối an toàn. Các DLL cần thiết nằm trong thư mục nhị phân.

Trang web cũng yêu cầu xác thực và tôi đã bao gồm người dùng/thẻ vào trong URL như trong ví dụ bên dưới. Trong ngắn hạn này là mã số:

URI := TIdURI.Create('https://test.example.com/'); 
URI.Username := ParamUserName; 
URI.Password := ParamPassword; 

HTTP := TIdHTTP.Create(nil); 
if URI.Protocol = 'https' then 
begin 
    IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); 
    IOHandler.SSLOptions.Method := sslvSSLv3; 
    HTTP.IOHandler := IOHandler; 
end; 

HTTP.Get(URI.GetFullURI([ofAuthInfo]), FileStream); 

Sử dụng mã này tôi nhận được một "Read Timeout" EIdReadTimeout ngoại lệ rất nhanh. Kiểm tra URL trong trình duyệt hoạt động không có vấn đề gì. Bất kỳ ý tưởng về những gì còn thiếu hoặc những gì tôi đã làm sai?

+0

Có tường lửa/proxy nằm giữa ứng dụng và máy chủ không? 'Trình duyệt hoạt động' không có nghĩa là có kết nối Internet trực tiếp. – mjn

+0

@mjustin Nếu tôi nhìn vào cài đặt trình duyệt thì không có proxy nào được xác định. Ngoài ra, thực tế là cách tiếp cận WinInet hoạt động mà không cần thiết lập bất kỳ proxy nói với tôi rằng đó không phải là vấn đề. – Tihauan

+3

Không sử dụng các thuộc tính TIdURI.Username/password trong tình huống này. Thay vào đó, bạn phải sử dụng thuộc tính TIdHTTP.Username/Password. –

Trả lời

9

Cuối cùng tôi đã từ bỏ Indy và OpenSSL và sử dụng WinInet để tải xuống. Đây là mã làm việc cho tôi:

function Download(URL, User, Pass, FileName: string): Boolean; 
const 
    BufferSize = 1024; 
var 
    hSession, hURL: HInternet; 
    Buffer: array[1..BufferSize] of Byte; 
    BufferLen: DWORD; 
    F: File; 
begin 
    Result := False; 
    hSession := InternetOpen('', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ; 

    // Establish the secure connection 
    InternetConnect (
    hSession, 
    PChar(FullURL), 
    INTERNET_DEFAULT_HTTPS_PORT, 
    PChar(User), 
    PChar(Pass), 
    INTERNET_SERVICE_HTTP, 
    0, 
    0 
    ); 

    try 
    hURL := InternetOpenURL(hSession, PChar(URL), nil, 0, 0, 0) ; 
    try 
     AssignFile(f, FileName); 
     Rewrite(f,1); 
     try 
     repeat 
      InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) ; 
      BlockWrite(f, Buffer, BufferLen) 
     until BufferLen = 0; 
     finally 
     CloseFile(f) ; 
     Result := True; 
     end; 
    finally 
     InternetCloseHandle(hURL) 
    end 
    finally 
    InternetCloseHandle(hSession) 
    end; 
end; 
+0

Một lời cảnh cáo liên quan đến mã ở trên: bạn nên luôn sử dụng tham số INTERNET_FLAG_RELOAD để buộc tải xuống từ máy chủ chứ không phải bộ nhớ cache. Tôi khuyên bạn nên thay đổi mã của mình thành: hURL: = InternetOpenURL (hSession, PChar (fullURL) , nil, 0, INTERNET_FLAG_RELOAD, 0); – user2858981

0

Tất cả các chức năng liên quan đến SSL cho kết nối an toàn sẽ không thành công trừ khi một số thư viện bổ sung được cài đặt đúng cách.

1.) Download libraries

2.) giải nén và copy cả DLL vào thư mục dự án của bạn (hoặc đâu đó trong PATH của hệ thống của bạn)

với mã của bạn từ các câu hỏi hoạt động tốt đối với tôi.

--reinhard

+0

Cảm ơn câu trả lời của bạn. Tôi đã có các DLL tại chỗ và có vẻ như chúng được nạp một cách chính xác. Thời gian chờ đọc có vẻ do nguyên nhân khác gây ra. Cách tiếp cận WinInet hoạt động với cùng một máy chủ. – Tihauan

1

Tôi đã thấy điều tương tự. Đặt TIdHTTP.ReadTimeout thành 0 để khắc phục sự cố cho tôi.

... 
HTTP.IOHandler := IOHandler; 
HTTP.ReadTimeout := 0; 
+0

ReadTimeout = 0 là giá trị thời gian chờ mặc định, và nó đại diện cho một thời gian chờ vô hạn. –

+0

Có, nhưng thiết lập nó trong mã sau khi gắn IOHandler dường như dừng ngoại lệ EIdReadTimeout khỏi bị ném. (Ít nhất là trong kinh nghiệm của tôi, với các phiên bản Indy đi kèm với Delphi) – jasonpenny

Các vấn đề liên quan