簡體   English   中英

如何使用 get 請求的響應通過 aiohttp 上傳文件?

[英]How can I upload files through aiohttp using response from get request?

首先,我正在為 WordPress REST API 編寫一個異步包裝器。我在 Bluehost 上托管了一個 Wordpress 網站。 我正在使用媒體(圖像)上傳端點。 我已成功上傳圖片,但我想進行 2 處更改。 第二個變化是我真正想要的,但出於好奇,我也想知道如何實施變化 1。 我會先提供代碼,然后再提供一些細節。

工作代碼

async def upload_local_pic2(self, local_url, date, title):
    url = f'{self.base_url}/wp-json/wp/v2/media'
    with aiohttp.MultipartWriter() as mpwriter:
      json = {'title': title, 'status':'publish'}
      mpwriter.append_json(json)
      with open(local_url, 'rb') as f:
        print(f)
        payload = mpwriter.append(f)
        async with self.session.post(url, data=payload) as response:
          x = await response.read()
          print(x)

變化 1

第一個變化是使用 aiofiles.open() 而不是僅僅使用 open() 上傳,因為我希望處理大量文件。 以下代碼不起作用。

async def upload_local_pic(self, local_url, date, title):
    url = f'{self.base_url}/wp-json/wp/v2/media'
    with aiohttp.MultipartWriter() as mpwriter:
      json = {'title': title, 'status':'publish'}
      mpwriter.append_json(json)
      async with aiofiles.open(local_url, 'rb') as f:
        print(f)
        payload = mpwriter.append(f)
        async with self.session.post(url, data=payload) as response:
          x = await response.read()
          print(x)

變2

我的另一個變化是我想再有一個function可以直接把文件上傳到WordPress的服務器,不用本地下載。 所以我不想獲取本地圖片,而是想傳入一張在線圖片的url。 以下代碼也不起作用。

async def upload_pic(self, image_url, date, title):
    url = f'{self.base_url}/wp-json/wp/v2/media'
    with aiohttp.MultipartWriter() as mpwriter:
      json = {'title':title, 'status':'publish'}
      mpwriter.append_json(json)
      async with self.session.get(image_url) as image_response:
        image_content = image_response.content
        print(image_content)
        payload = mpwriter.append(image_content)
        async with self.session.post(url, data = payload) as response:
          x = await response.read()
          print(x)

細節/調試

我試圖弄清楚為什么每個都不起作用。 我認為關鍵是調用print(image_content)print(f)顯示我輸入到mpwriter.append的內容

在我只使用標准 Python open() function 的示例中,我顯然傳入了<_io.BufferedReader name='/redactedfilepath/index.jpeg'>

在帶有 aiofile 的更改 1 示例中,我傳入<aiofiles.threadpool.binary.AsyncBufferedReader object at 0x7fb803122250> Wordpress 將返回此 html:

b'<head><title>Not Acceptable.</title></head><body><h1>Not Acceptable.</h1><p>An appropriate representation of the requested resource could not be found on this server. This error was generated by Mod_Security.</p></body></html>'

最后,在更改 2 中,我嘗試將 get 請求傳遞給 url 給我,我得到了<StreamReader 292 bytes> WordPress 返回的響應與上面的 Mod Security 相同。

知道如何使這些示例起作用嗎? 看起來它們都是某種類型的 io 閱讀器,但我猜底層 aiohttp 代碼對它們的處理方式不同。

此外,這並不重要, 但這是我傳遞給更改 2 示例的 url。

好的,所以我想出了兩個變化。

對於嘗試使用aiofiles讀取文件時的第一個更改,我只需要讀取整個文件而不是傳入文件處理程序。 另外,我需要手動設置內容配置。

async def upload_local_pic(self, local_url, date, title):
    url = f'{self.base_url}/wp-json/wp/v2/media'
    with aiohttp.MultipartWriter() as mpwriter:
      json = {'status':'publish'}
      mpwriter.append_json(json)
      async with aiofiles.open(local_url, mode='rb') as f:
        contents = await f.read()
        payload = mpwriter.append(contents)
        payload.set_content_disposition('attachment', filename= title+'.jpg')
        async with self.session.post(url, data=payload) as response:
          x = await response.read()
          print(x)

對於第二個更改,它是一個類似的概念,只是直接從 URL 上傳文件。 我需要先讀取整個內容,而不是傳入將讀取內容的處理程序。 我還需要手動設置內容配置。

async def upload_pic(self, image_url, date, title):
    url = f'{self.base_url}/wp-json/wp/v2/media'
    with aiohttp.MultipartWriter() as mpwriter:
      json = {'status':'publish'}
      mpwriter.append_json(json)
      async with self.session.get(image_url) as image_response:
        image_content = await image_response.read()
        payload = mpwriter.append(image_content)
        payload.set_content_disposition('attachment', filename=title+'.jpg')
        async with self.session.post(url, data = payload) as response:
          x = await response.read()
          print(x)

我只會回答帖子的標題(而不是中間的問題)。

下面的代碼應該給出一個簡短的示例,說明如何將文件從 URL#1 上傳到 URL#2(無需將文件下載到本地計算機,然后才進行上傳)。

我在這里舉兩個例子:

  1. 將文件全部內容讀入memory(不是下載)。 這在處理大文件時當然不太好......
  2. 以塊的形式讀取和發送文件(因此我們不會一次讀取所有文件內容)。

示例 #1:一次讀取所有文件內容並上傳

import asyncio
import aiohttp 

async def http_upload_from_url(src, dst):
    async with aiohttp.ClientSession() as session:
        src_resp = await session.get(src)
        #print(src_resp)
        dst_resp = await session.post(dst, data=src_resp.content)
        #print(dst_resp)

try:
    asyncio.run(http_upload_from_url(SRC_URL, DST_URL))
except Exception as e:
    print(e)

示例 #2:以塊的形式讀取文件內容並上傳

import asyncio
import aiohttp 

async def url_sender(url=None, chunk_size=65536):
    async with aiohttp.ClientSession() as session:
        resp = await session.get(url)
        #print(resp)
        async for chunk in resp.content.iter_chunked(chunk_size):
            #print(f"send chunk with size {len(chunk)}")
            yield chunk

async def chunked_http_upload_from_url(src, dst):
    async with aiohttp.ClientSession() as session:
        resp = await session.post(dst, data=url_sender(src))
        #print(resp)
        #print(await resp.text())

try:
    asyncio.run(chunked_http_upload_from_url(SRC_URL, DST_URL))
except Exception as e:
    print(e)

一些注意事項:

  • 您需要定義 SRC_URL 和 DST_URL。
  • 我只添加了用於調試的打印件(以防您沒有收到 [200 OK] 響應)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM