كيفية تنزيل ملف عبر HTTPS باستخدام Indy 10 و Openssl؟
-
19-09-2019 - |
سؤال
لدي المهمة التالية: قم بتنزيل ملف باستخدام HTTPS والمصادقة. Indy يبدو أن الطريق للذهاب ولكن لسبب ما لا يعمل حتى الآن. لدي ما يلي في المكان:
- مكون Tidhttp الذي استخدمه للتنزيل
- مكون Tiduri يستخدم لإنشاء عنوان URL
- مكون tidssliohandlersocketopenssl الذي يجب أن يوفر الاتصال الآمن. DLLs المطلوبة موجودة في المجلد الثنائي.
يتطلب الموقع أيضا المصادقة وأدرج المستخدم / تمرير المستخدم في عنوان URL كما في المثال أدناه. باختصار هذا هو الرمز:
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);
باستخدام هذا الرمز أحصل على "قراءة مهلة" استثناء Eidreadtimeout بسرعة كبيرة. اختبار عنوان URL في متصفح يعمل دون مشكلة. أي أفكار حول ما هو مفقود أم ما فعلت خطأ؟
المحلول
لقد تخلت أخيرا Indy و Openssl واستخدم Wininet للتنزيل. هذا هو التعليمات البرمجية التي عملت بالنسبة لي:
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;
نصائح أخرى
لقد رأيت نفس الشيء. إعداد Tidhttp.ReadTimeout إلى الصفر يعمل على إصلاح المشكلة بالنسبة لي.
...
HTTP.IOHandler := IOHandler;
HTTP.ReadTimeout := 0;
ستفشل جميع الوظائف ذات الصلة SSL للاتصالات الآمنة ما لم يتم تثبيت بعض المكتبات الإضافية بشكل صحيح.
1.) تحميل المكتبات
2.) Unzip ونسخ كل من DLLs إلى مجلد المشروع الخاص بك (أو في مكان ما في مسار نظامك)
مع هذا الكود الخاص بك من السؤال يعمل بشكل جيد بالنسبة لي.
- reinhard.