使用Paramiko上传类似文件的对象?

时间:2011-05-06 17:10:57

标签: python paramiko

我有一堆看起来像这样的代码:

with tempfile.NamedTemporaryFile() as tmpfile:
    tmpfile.write(fileobj.read()) # fileobj is some file-like object
    tmpfile.flush()
    try:
        self.sftp.put(tmpfile.name, path)
    except IOError:
        # error handling removed for ease of reading
        pass

是否可以像这样进行上传而无需将文件写出来?

2 个答案:

答案 0 :(得分:14)

更新自Paramiko 1.10 起,您可以使用putfo

self.sftp.putfo(fileobj, path)

您可以使用paramiko.SFTPClient.put而不是paramiko.SFTPClient.open,这会打开一个类似file的对象。你可以写信给那个。像这样:

f = self.sftp.open(path, 'wb')
f.write(fileobj.read())
f.close()

请注意,以32 KiB块的形式提供paramiko数据可能是值得的,因为这是SSH协议可以处理的最大块,而不会将其分解为多个数据包。

答案 1 :(得分:2)

StringIO您要找的是什么? (doc page

SFTPClient的{​​{1}}和get()函数采用路径而不是文件句柄,这会让事情变得有点尴尬。

您可以为put()编写一个包装器,为其提供所需的功能。

这是我未经测试的最佳尝试:

paramiko.SFTPClient

如果有效,from paramiko import SFTPClient class SFTPClient2(SFTPClient): def put(self, local_file, remotepath, callback=None, confirm=True): fl = source_file file_size = os.fstat(fl.fileno()).st_size try: fr = self.file(remotepath, 'wb') fr.set_pipelined(True) size = 0 try: while True: data = fl.read(32768) if len(data) == 0: break fr.write(data) size += len(data) if callback is not None: callback(size, file_size) finally: fr.close() finally: fl.close() if confirm: s = self.stat(remotepath) if s.st_size != size: raise IOError('size mismatch in put! %d != %d' % (s.st_size, size)) else: s = SFTPAttributes() return s def get(self, remotepath, local_file, callback=None): fr = self.file(remotepath, 'rb') file_size = self.stat(remotepath).st_size fr.prefetch() try: fl = local_file try: size = 0 while True: data = fr.read(32768) if len(data) == 0: break fl.write(data) size += len(data) if callback is not None: callback(size, file_size) finally: fl.close() finally: fr.close() s = os.fstat(fl.fileno()) if s.st_size != size: raise IOError('size mismatch in get! %d != %d' % (s.st_size, size)) get函数现在应该使用本地文件句柄而不是路径。

我所要做的就是摆脱从路径中打开文件的代码,并将获取文件大小的代码更改为使用put而不是os.fstat