10

次のようなコードがたくさんあります。

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

ファイルをどこかに書き出すことなく、このようなアップロードを行うことは可能ですか?

4

2 に答える 2

20

更新Paramiko 1.10以降、 putfoを使用できます。

self.sftp.putfo(fileobj, path)

を使用する代わりに、 のようなオブジェクトを開くparamiko.SFTPClient.putを使用できます。あなたはそれに書くことができます。このようなもの:paramiko.SFTPClient.openfile

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

paramiko データを 32 KiB チャンクでフィードする価値があることに注意してください。これは、SSH プロトコルが複数のパケットに分割せずに処理できる最大のチャンクであるためです。

于 2011-05-06T17:43:45.690 に答える
2

StringIOあなたが探しているものは何ですか?(ドキュメントページ

SFTPClientと関数はファイルハンドルではなくパス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))

それが機能する場合、getandput関数はパスではなくローカルファイルハンドルを使用する必要があります。

os.fstatパスからファイルを開くコードを削除し、の代わりに使用するファイルのサイズを取得するコードを変更するだけで済みos.statました。

于 2011-05-06T17:26:30.523 に答える