2017-08-24 2 views
3

マルチパート/フォームデータをコンテンツタイプとして取得するAPIエンドポイントによってファイルをアップロードする機会はありますかそのファイルのURL?アップロードする必要があるファイルへのURLのみを持つマルチパート/フォームのアップロード方法(チャンク)

ルール: ファイル全体をメモリにダウンロードし、このエンドポイントでアップロードするオプションはありません(テンポラリファイルを格納するのに十分な大きさのボックスが保証されることはありません)。

質問: 1つのサーバー(GET)から別のサーバー(multipart/form-data POST)にチャンクでファイルをストリーミングしたいとします。これは可能ですか?それを達成する方法?

フロー: FILE_SERVER < -GET- my_script.py -POST->ここでは、サーバ

をアップロードメモリにダウンロードする簡単な例(RAM)オプション(それはルールに対してです)です:

from io import BytesIO 

import requests 
from requests_toolbelt.multipart.encoder import MultipartEncoder 

file_url = 'https://www.sysaid.com/wp-content/uploads/features/itam/image-banner-asset.png' 
requested_file_response = requests.get(file_url, stream=True) 

TOKEN_PAYLOAD = { 
    'grant_type': 'password', 
    'client_id': '#########', 
    'client_secret': '#########', 
    'username': '#########', 
    'password': '#########' 
} 


def get_token(): 
    response = requests.post(
     'https://upload_server/oauth/token', 
     params=TOKEN_PAYLOAD) 
    response_data = response.json() 
    token = response_data.get('access_token') 
    if not token: 
     print("token error!") 
    return token 

token = get_token() 

file_object = BytesIO() 
file_object.write(requested_file_response.content) 

# Form conctent 
multipart_data = MultipartEncoder(
    fields={ 
     '--': (
      'test.png', 
      file_object # AttributeError: 'generator' object has no attribute 'encode' when I try to pass generator here. 
     ), 
     'id': '2217', 
     'fileFieldDefId': '4258', 
    } 
) 

# Create headers 
headers = { 
    "Authorization": "Bearer {}".format(token), 
    'Content-Type': multipart_data.content_type 
} 

session = requests.Session() 
response = session.post(
    'https://upload_server/multipartUpdate', 
    headers=headers, 
    data=multipart_data, 
) 

答えはストリーム目的のオブジェクト作成のようなファイルにあります

ありがとうございました。乾杯!

答えて

3

私はそれが(私達はちょうどrequests.get(..., stream=True).rawを渡すことによって得ることができる)ファイルを.read()能力だけでなく、ストリームに残っているどのくらいのデータを決定するために何らかの方法があることだけでなく、必要と右よりrequests_toolbeltソースコードを読んでいる場合。あなたは常に有効content-lengthヘッダーを持っていることを確信していると仮定すると、

、これは私が提案するソリューションのようになります。

import requests 
from requests_toolbelt.multipart.encoder import MultipartEncoder 

file_url = 'https://www.sysaid.com/wp-content/uploads/features/itam/image-banner-asset.png' 
target = 'http://localhost:5000/test' 


class PinocchioFile: 
    """I wish I was a real file""" 

    def __init__(self, url): 
     self.req = requests.get(url, stream=True) 
     length = self.req.headers.get('content-length') 
     self.len = None if length is None else int(length) 
     self._raw = self.req.raw 

    def read(self, chunk_size): 
     chunk = self._raw.read(chunk_size) or b'' 
     self.len -= len(chunk) 
     if not chunk: 
      self.len = 0 
     return chunk 


multipart_data = MultipartEncoder(
    fields={ 
     '--': (
      'test.png', 
      PinocchioFile(file_url), 
     ), 
     'id': '2217', 
     'fileFieldDefId': '4258', 
    } 
) 

# Create headers 
headers = { 
    'Content-Type': multipart_data.content_type 
} 

response = requests.post(
    target, 
    data=multipart_data, 
    headers=headers, 
) 
+0

素敵やりました!ありがとう。 –

関連する問題