@@ -959,7 +959,7 @@ def _ftp_login(ftp, user, pw):
959959 pw = "anonymous" if user == "anonymous" else ""
960960 ftp .login (user , pw )
961961
962- def download_file_from_ftp_file (url ):
962+ def download_file_from_ftp_file (url , returnstats = False ):
963963 p = urlparse (url )
964964 if p .scheme not in ("ftp" , "ftps" ):
965965 return False
@@ -990,17 +990,21 @@ def download_file_from_ftp_file(url):
990990 bio = MkTempFile ()
991991 ftp .retrbinary ("RETR " + retr_path , bio .write )
992992 ftp .quit ()
993+ fulldatasize = bio .tell ()
993994 bio .seek (0 , 0 )
994- return bio
995+ if (returnstats ):
996+ returnval = {'Type' : "Buffer" , 'Buffer' : bio , 'Contentsize' : fulldatasize , 'ContentsizeAlt' : {'IEC' : get_readable_size (fulldatasize , 2 , "IEC" ), 'SI' : get_readable_size (fulldatasize , 2 , "SI" )}, 'Headers' : None , 'Version' : None , 'Method' : None , 'HeadersSent' : None , 'URL' : url , 'Code' : None , 'FTPLib' : 'pyftp' }
997+ else :
998+ return bio
995999 except Exception :
9961000 try :
9971001 ftp .close ()
9981002 except Exception :
9991003 pass
10001004 return False
10011005
1002- def download_file_from_ftp_string (url ):
1003- fp = download_file_from_ftp_file (url )
1006+ def download_file_from_ftp_string (url , returnstats = False ):
1007+ fp = download_file_from_ftp_file (url , returnstats )
10041008 return fp .read () if fp else False
10051009
10061010def upload_file_to_ftp_file (fileobj , url ):
@@ -1062,7 +1066,7 @@ def upload_file_to_ftp_string(data, url):
10621066# SFTP helpers
10631067# --------------------------
10641068
1065- def download_file_from_sftp_file (url ):
1069+ def download_file_from_sftp_file (url , returnstats = False ):
10661070 if not haveparamiko :
10671071 return False
10681072 p = urlparse (url )
@@ -1083,17 +1087,21 @@ def download_file_from_sftp_file(url):
10831087 sftp .getfo (path , bio )
10841088 sftp .close ()
10851089 ssh .close ()
1090+ fulldatasize = bio .tell ()
10861091 bio .seek (0 , 0 )
1087- return bio
1092+ if (returnstats ):
1093+ returnval = {'Type' : "Buffer" , 'Buffer' : bio , 'Contentsize' : fulldatasize , 'ContentsizeAlt' : {'IEC' : get_readable_size (fulldatasize , 2 , "IEC" ), 'SI' : get_readable_size (fulldatasize , 2 , "SI" )}, 'Headers' : None , 'Version' : None , 'Method' : None , 'HeadersSent' : None , 'URL' : url , 'Code' : None , 'SFTPLib' : 'paramiko' }
1094+ else :
1095+ return bio
10881096 except Exception :
10891097 try :
10901098 ssh .close ()
10911099 except Exception :
10921100 pass
10931101 return False
10941102
1095- def download_file_from_sftp_string (url ):
1096- fp = download_file_from_sftp_file (url )
1103+ def download_file_from_sftp_string (url , returnstats = False ):
1104+ fp = download_file_from_sftp_file (url , returnstats )
10971105 return fp .read () if fp else False
10981106
10991107def upload_file_to_sftp_file (fileobj , url ):
@@ -1141,12 +1149,51 @@ def upload_file_to_sftp_string(data, url):
11411149 pass
11421150 return out
11431151
1144- # Optional pysftp shims (kept for compatibility)
1145- def download_file_from_pysftp_file (url ):
1152+ # --------------------------
1153+ # Pysftp Compatibility Layer
1154+ # --------------------------
1155+
1156+ def download_file_from_pysftp_file (url , returnstats = False ):
11461157 if not havepysftp :
11471158 return False
1148- # pysftp is a thin wrapper over paramiko; keep behavior similar by delegating.
1149- return download_file_from_sftp_file (url )
1159+ p = urlparse (url )
1160+ if p .scheme not in ("sftp" , "scp" ):
1161+ return False
1162+
1163+ host = p .hostname
1164+ port = p .port or 22
1165+ user = p .username or "anonymous"
1166+ pw = p .password or ("anonymous" if user == "anonymous" else "" )
1167+ path = p .path or "/"
1168+
1169+ conn = None
1170+ try :
1171+ # NOTE: pysftp host key checking is strict by default.
1172+ # If you need AutoAddPolicy-like behavior, set cnopts (see note below).
1173+ conn = pysftp .Connection (host = host , port = port , username = user , password = pw )
1174+
1175+ sftp = conn .sftp_client
1176+ bio = BytesIO ()
1177+ sftp .getfo (path , bio )
1178+
1179+ fulldatasize = bio .tell ()
1180+ bio .seek (0 , 0 )
1181+
1182+ fulldatasize = bio .tell ()
1183+ bio .seek (0 , 0 )
1184+ if (returnstats ):
1185+ returnval = {'Type' : "Buffer" , 'Buffer' : bio , 'Contentsize' : fulldatasize , 'ContentsizeAlt' : {'IEC' : get_readable_size (fulldatasize , 2 , "IEC" ), 'SI' : get_readable_size (fulldatasize , 2 , "SI" )}, 'Headers' : None , 'Version' : None , 'Method' : None , 'HeadersSent' : None , 'URL' : url , 'Code' : None , 'SFTPLib' : 'pysftp' }
1186+ else :
1187+ return bio
1188+
1189+ except Exception :
1190+ return False
1191+ finally :
1192+ try :
1193+ if conn is not None :
1194+ conn .close ()
1195+ except Exception :
1196+ pass
11501197
11511198def download_file_from_pysftp_string (url ):
11521199 fp = download_file_from_pysftp_file (url )
@@ -1155,7 +1202,43 @@ def download_file_from_pysftp_string(url):
11551202def upload_file_to_pysftp_file (fileobj , url ):
11561203 if not havepysftp :
11571204 return False
1158- return upload_file_to_sftp_file (fileobj , url )
1205+ p = urlparse (url )
1206+ if p .scheme not in ("sftp" , "scp" ):
1207+ return False
1208+
1209+ host = p .hostname
1210+ port = p .port or 22
1211+ user = p .username or "anonymous"
1212+ pw = p .password or ("anonymous" if user == "anonymous" else "" )
1213+ path = p .path or "/"
1214+
1215+ conn = None
1216+ try :
1217+ conn = pysftp .Connection (host = host , port = port , username = user , password = pw )
1218+
1219+ sftp = conn .sftp_client
1220+ try :
1221+ fileobj .seek (0 , 0 )
1222+ except Exception :
1223+ pass
1224+
1225+ sftp .putfo (fileobj , path )
1226+
1227+ try :
1228+ fileobj .seek (0 , 0 )
1229+ except Exception :
1230+ pass
1231+
1232+ return fileobj
1233+
1234+ except Exception :
1235+ return False
1236+ finally :
1237+ try :
1238+ if conn is not None :
1239+ conn .close ()
1240+ except Exception :
1241+ pass
11591242
11601243def upload_file_to_pysftp_string (data , url ):
11611244 if not havepysftp :
@@ -1565,7 +1648,7 @@ def parse_pycurl_verbose(fileobj_or_text):
15651648 'response' : parse_response_block (resp_block ) if resp_block else None ,
15661649 }
15671650
1568- def download_file_from_http_file (url , headers = None , usehttp = __use_http_lib__ , httpuseragent = None , httpreferer = None , httpcookie = geturls_cj , httpmethod = "GET" , postdata = None , returnstat = False ):
1651+ def download_file_from_http_file (url , headers = None , usehttp = __use_http_lib__ , httpuseragent = None , httpreferer = None , httpcookie = geturls_cj , httpmethod = "GET" , postdata = None , returnstats = False ):
15691652 if headers is None :
15701653 headers = {}
15711654 else :
@@ -1925,8 +2008,8 @@ def download_file_from_http_file(url, headers=None, usehttp=__use_http_lib__, ht
19252008 else :
19262009 return httpfile
19272010
1928- def download_file_from_http_string (url , headers = None , usehttp = __use_http_lib__ , httpuseragent = None , httpreferer = None , httpcookie = geturls_cj , httpmethod = "GET" , returnstat = False ):
1929- fp = download_file_from_http_file (url , headers , usehttp , httpuseragent , httpreferer , httpcookie , httpmethod , returnstat )
2011+ def download_file_from_http_string (url , headers = None , usehttp = __use_http_lib__ , httpuseragent = None , httpreferer = None , httpcookie = geturls_cj , httpmethod = "GET" , returnstats = False ):
2012+ fp = download_file_from_http_file (url , headers , usehttp , httpuseragent , httpreferer , httpcookie , httpmethod , returnstats )
19302013 return fp .read () if fp else False
19312014
19322015# --------------------------
0 commit comments