2

私はSpiderOakによるこのZipstreamモジュールをいじくり回してきました。これにより、基本的に、ディスクに何も書き込まずにファイルまたはフォルダーをストリーミングおよびzipできます。不規則なサイズのデータ​​のチャンクが生成されます。

現在、投稿リクエスト内のフィールドfileとフィールドを送信する必要があるファイルホスティングサイトにディレクトリをアップロードしようとしています。apikeyリクエストでは、次のように apikey の dict を作成する必要があります。

data = {'apikey': 'myapikey'}

また、zipstream 全体を文字列に読み取り、それをファイル エンコーディング dict に渡します。

files = {'file': ('mydir.zip', the_string_that_is_a_zipped_dir)}

次に、リクエストを発行します

r = requests.post(url, data=data, files=files).

これは正常に動作します。ただし、将来的にはより大きなものを転送したいと考えており、メモリ内のファイル全体を読み取ることは、そもそも悪い考えです。リクエストの高度なセクションで、ジェネレーターをデータ フィールドとして送信できることを見ましたが、API キーを送信できず、ヘッダーを手動で変更してコンテンツ タイプなどを設定する必要があるため、機能しません。また、次のように、API キーと zip ファイル ジェネレーターから辞書を作成しようとしました。

しかし、これは(予想どおり)失敗します。

マルチパートフォームデータのファイルの文字列を生成するジェネレーターを使用してリクエストをハックする方法はありますか?

4

1 に答える 1

0

OK、苦労した後、モジュールposterを使用する代わりに、リクエストなしでこれを機能させることができました。

最初に、zipstream の周りに fileobject ラッパーを次のように作成しました。

from zipstream import ZipStream

class Zipit:
  def __init__( self, path):
    self.it = iter(ZipStream(path,compression=0))
    self.next_chunk = ""
    self.length = -1
    self.path = path
    self.__is_zipit__=''    
  @property
  def size(self):
    if self.length < 0:
      self.length = 0
      zip_object = ZipStream(self.path,compression=0)
      for data in zip_object:
        self.length += len(data)
    return self.length

  def growChunk( self ):
    self.next_chunk = self.next_chunk + self.it.next()
  def read( self, n ):
    if self.next_chunk == None:
      return None
    try:
      while len(self.next_chunk)<n:
        self.growChunk()
      rv = self.next_chunk[:n]
      self.next_chunk = self.next_chunk[n:]
      return rv
    except StopIteration:
      rv = self.next_chunk
      self.next_chunk = None
      return rv

簡単なAPI(SOの別の例から恥知らずに適応されたコード)を持つために。

次に、ポスターのドキュメントに従って、必要なマルチパート オブジェクトを作成します。

z = Zipit('/my/path/to/zip')

f = MultipartParam('file', fileobj=z, filesize=z.size, filename='test.zip',filetype='application/zip')
datagen, headers = multipart_encode([ f, ('akey', 'mykey')])

最後のハックは、fileobject フィールドが Zipit インスタンスの場合にリセットをスキップすることです。

   def reset(self):
        if hasattr(self.fileobj, '__is_zipit__'): return
        if self.fileobj is not None:
            self.fileobj.seek(0)
        elif self.value is None:
            raise ValueError("Don't know how to reset this parameter")

これは私にとってはうまくいきました。これを読んでいる5人の誰かの助けになれば幸いです。

于 2014-06-24T11:33:47.193 に答える