El problema que tienes es que no estas creando el stream antes de usarlo.
De todas formas aquí te va un ejemplo de como bajar todos los ficheros de un directorio conociendo su extension:
program EjemploSftp; {$APPTYPE CONSOLE} uses Windows, Sysutils, Classes, Curl in 'Curl.pas'; function downloadFile(url, user, password: AnsiString; localPath: String): CURLCode; var hCurl: TCurl; fileStream: TFileStream; begin Result:= CURLE_OK; hCurl:= curl_easy_init; if hCurl <> nil then try if curl_easy_setopt(hCurl, CURLOPT_VERBOSE, TRUE) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_USE_SSL, CURLUSESSL_ALL) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_SSL_VERIFYPEER, FALSE) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_USERNAME, PAnsiChar(user)) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_PASSWORD, PAnsiChar(password)) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_URL, PAnsiChar(url)) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, @CurlSaveToStream) <> CURLE_OK then Exit; fileStream:= TFileStream.Create(localPath, fmCreate); try if curl_easy_setopt(hCurl, CURLOPT_FILE, fileStream) <> CURLE_OK then Exit; Result:= curl_easy_perform(hCurl); finally fileStream.Free; end; finally curl_easy_cleanup(hCurl); end; end; function downloadDir(url, user, password, fileExt: AnsiString; localPath: String): CURLCode; var i: Integer; hCurl: TCurl; list: TMemoryStream; name: String; begin Result:= CURLE_OK; if Copy(url, High(url), 1) <> '/' then url:= url + '/'; hCurl:= curl_easy_init; if hCurl <> nil then try if curl_easy_setopt(hCurl, CURLOPT_VERBOSE, TRUE) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_USE_SSL, CURLUSESSL_ALL) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_SSL_VERIFYPEER, FALSE) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_USERNAME, PAnsiChar(user)) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_PASSWORD, PAnsiChar(password)) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_URL, PAnsiChar(url)) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_DIRLISTONLY, TRUE) <> CURLE_OK then Exit; if curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, @CurlSaveToStream) <> CURLE_OK then Exit; list:= TMemoryStream.Create; try if curl_easy_setopt(hCurl, CURLOPT_FILE, list) <> CURLE_OK then Exit; Result:= curl_easy_perform(hCurl); with TStringList.Create do try list.Position:= 0; LoadFromStream(list); localPath:= IncludeTrailingPathDelimiter(ExpandFileName(localPath)); if not ForceDirectories(localPath) then Exit; for i:= 0 to Count - 1 do begin name:= Strings[i]; if (name <> '.') and (name <> '..') then if ExtractFileExt(name) = fileExt then downloadFile(url + name, user, password, localPath + name); end; finally Free; end; finally list.Free; end; finally curl_easy_cleanup(hCurl); end; end; begin downloadDir('sftp://test.rebex.net:22', 'demo', 'password', '.txt', 'c:\abc'); end.
Esta hecho de forma rápida, funciona, pero seguro que tendrás que pulir algunas cosas
Saludos