2011-05-06 3 views
8

다음과 같은 코드가 있습니다.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 

어딘가에 파일을 쓰지 않고도 업로드를 할 수 있습니까?

답변

12

업데이트 Paramiko 1.10의, 당신은 putfo를 사용할 수 있습니다

self.sftp.putfo(fileobj, path) 

대신 paramiko.SFTPClient.put를 사용하여, 당신은 file -like 객체를 엽니 다 paramiko.SFTPClient.open를 사용할 수 있습니다. 당신은 그것에 쓸 수 있습니다. 이런 식으로 뭔가 : 즉 가장 큰 덩어리 기본 SSH 프로토콜 여러 패킷으로 그것을 파괴하지 않고 처리 할 수 ​​이후는 32 개 킬로바이트 청크에 paramiko 데이터를 공급하는 가치가있을 수 있음을

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

참고.

2

StringIO 무엇입니까? ( doc page)

SFTPClientget()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)) 

에서, getput 기능은 이제 로컬 파일 핸들이 아닌 경로를 취해야한다 :

여기 최선 검증되지 않은 시도이다.

경로에서 파일을 여는 코드를 제거하고 파일 크기를 가져 오는 코드를 os.fstat 대신 os.stat 대신 변경해야했습니다.

+0

아니요, 이미 파일과 유사한 객체가 있습니다. 문제는'paramiko.SFTPClient.put'가 파일 대신 경로를 사용한다는 것입니다. 어떤 경우에는 임시 파일에 쓰는 "파일"이 이미 StringIO 객체입니다. –

+0

paramiko의 소스를 살펴 보았는데 함수가 경로를 취한다는 것을 알았습니다. 위의 붙여 넣은 함수를 수정하기 위해 약간의 래퍼를 작성했습니다. – Acorn

관련 문제