我正在嘗試制作一個將檔案上傳到我的谷歌驅動器的功能。
下面的代碼上傳一個帶有請求的檔案。
import requests
import json
with open('storage.json', 'r') as file:
token = json.load(file)
token = token["access_token"]
url = "https://www.googleapis.com/upload/drive/v3/files"
file_metadata = {"name": "test.jpg",
"parents": [],
}
data = {
"MetaData": (
"metadata",
json.dumps(file_metadata),
"application/json; charset=UTF-8",
),
"Media": open("test2.jpg", "rb"),
}
headers = {"Authorization": "Bearer {}".format(token)}
params = {"uploadType": "multipart"}
res = requests.post(url, files=data, params=params, headers=headers)
print(res.text)
現在,我想用 aiohttp 做一個異步函式。但是,我不知道該怎么做。下面是我當前的代碼,但它給出了 aiohttp.payload.LookupError。
async def upload_file(session, file_path, folder_id):
'''
* uploads a single file to the designated folder
* args:
- session: aiohttp session
- file_path : absolute path of a file (e.g.) C:\Git\GoogleDriveAPI\test2.jpg
- folder_id: folder id of the designated folder in google drive (e.g.) '1Q6gaU4kHaLRN5psS4S_2Yx_*******'
'''
file_name = file_path.split(os.path.sep)[-1]
url = "https://www.googleapis.com/upload/drive/v3/files"
file_metadata = {"name": file_name,
"parents": [folder_id],
}
data = {
"MetaData": (
"metadata",
json.dumps(file_metadata),
"application/json; charset=UTF-8",
),
"Media": open(file_path, "rb"),
}
global token
headers = {"Authorization": "Bearer {}".format(token)}
params = {"uploadType": "multipart"}
async with session.post(url, data=data, params=params, headers=headers) as resp:
print(resp.text)
這是我的完整代碼,以防您需要進行實驗。
import os
import sys
import argparse
import asyncio
import json
import aiohttp
from aiohttp import web
import googleapiclient.errors
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
from tqdm import tqdm
DEFAULT_CONCUR_REQ = 20
MAX_CONCUR_REQ = 1000
def get_token():
'''
* authorize access to user's google drive and return access token
* access information is stored as 'storage.json'
'''
SCOPES = 'https://www.googleapis.com/auth/drive.file'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
print("make new storage data file ")
flow = client.flow_from_clientsecrets('client_secret_drive.json', SCOPES)
creds = tools.run_flow(flow, store)
build('drive', 'v3', http=creds.authorize(Http()))
with open('storage.json', 'r') as f:
creds = json.load(f)
token = creds["access_token"]
return token
async def upload_file(session, file_path, folder_id):
'''
* uploads a single file to the designated folder
* args:
- session: aiohttp session
- file_path : absolute path of a file (e.g.) C:\Git\GoogleDriveAPI\test2.jpg
- folder_id: folder id of the designated folder in google drive (e.g.) '1Q6gaU4kHaLRN5psS4S_2Yx_*******'
'''
file_name = file_path.split(os.path.sep)[-1]
url = "https://www.googleapis.com/upload/drive/v3/files"
file_metadata = {"name": file_name,
"parents": [folder_id],
}
data = {
"MetaData": (
"metadata",
json.dumps(file_metadata),
"application/json; charset=UTF-8",
),
"Media": open(file_path, "rb"),
}
global token
headers = {"Authorization": "Bearer {}".format(token)}
params = {"uploadType": "multipart"}
async with session.post(url, data=data, params=params, headers=headers) as resp:
print(resp.text)
async def upload_files(file_paths, folder_id):
async with aiohttp.ClientSession() as session:
jobs = [upload_file(session, file_path, folder_id) for file_path in file_paths]
jobs = asyncio.as_completed(jobs)
for job in jobs:
await job
def main():
folder = r'C:\Git\GoogleDriveAPI\test2'
folder_id = None
files = os.listdir(folder)
file_paths = [os.path.join(folder, file) for file in files]
loop = asyncio.get_event_loop()
loop.run_until_complete(upload_files(file_paths, folder_id))
if __name__ == '__main__':
# parser = argparse.ArgumentParser(
# description='Upload folder including all sub-folders to google drive.')
# parser.add_argument('folder_path',
# help='folder_path: local folder path to upload'
# 'e.g. C:\Git\PytorchBasic')
# parser.add_argument('folder_id',
# help='folder_id: target folder\'s id in google drive'
# 'e.g. 1FzI5QChbh4Q-nEQGRu8D-********')
# args = parser.parse_args()
# if not os.path.isdir(args.folder_path):
# print('*** Folder path error: invalid path')
# parser.print_usage()
# sys.exit(1)
# folder_path = args.folder_path
# folder_id = args.folder_id
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
token = get_token()
main()
錯誤
C:\VirtualEnv\basic\Scripts\python.exe C:/Git/GoogleDriveAPI/googledriveapi_async.py
Traceback (most recent call last):
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 510, in update_body_from_data
body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 118, in get
raise LookupError()
aiohttp.payload.LookupError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 145, in _gen_form_data
part = payload.get_payload(
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 71, in get_payload
return PAYLOAD_REGISTRY.get(data, *args, **kwargs)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 118, in get
raise LookupError()
aiohttp.payload.LookupError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:/Git/GoogleDriveAPI/googledriveapi_async.py", line 103, in <module>
main()
File "C:/Git/GoogleDriveAPI/googledriveapi_async.py", line 81, in main
loop.run_until_complete(upload_files(file_paths, folder_id))
File "C:\Users\chsze\AppData\Local\Programs\Python\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
return future.result()
File "C:/Git/GoogleDriveAPI/googledriveapi_async.py", line 73, in upload_files
await job
File "C:\Users\chsze\AppData\Local\Programs\Python\Python38\lib\asyncio\tasks.py", line 619, in _wait_for_one
return f.result() # May raise f.exception().
File "C:/Git/GoogleDriveAPI/googledriveapi_async.py", line 65, in upload_file
async with session.post(url, data=data, params=params, headers=headers) as resp:
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client.py", line 1138, in __aenter__
self._resp = await self._coro
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client.py", line 507, in _request
req = self._request_class(
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 313, in __init__
self.update_body_from_data(data)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 512, in update_body_from_data
body = FormData(body)()
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 170, in __call__
return self._gen_form_data()
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 149, in _gen_form_data
raise TypeError(
TypeError: Can not serialize value type: <class 'tuple'>
headers: {}
value: ('metadata', '{"name": "COCO_train2014_000000000064.jpg", "parents": [null]}', 'application/json; charset=UTF-8')
Task exception was never retrieved
future: <Task finished name='Task-4' coro=<upload_file() done, defined at C:/Git/GoogleDriveAPI/googledriveapi_async.py:41> exception=TypeError('Can not serialize value type: <class \'tuple\'>\n headers: {}\n value: (\'metadata\', \'{"name": "COCO_train2014_000000000061.jpg", "parents": [null]}\', \'application/json; charset=UTF-8\')')>
Traceback (most recent call last):
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 510, in update_body_from_data
body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 118, in get
raise LookupError()
aiohttp.payload.LookupError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 145, in _gen_form_data
part = payload.get_payload(
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 71, in get_payload
return PAYLOAD_REGISTRY.get(data, *args, **kwargs)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 118, in get
raise LookupError()
aiohttp.payload.LookupError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:/Git/GoogleDriveAPI/googledriveapi_async.py", line 65, in upload_file
async with session.post(url, data=data, params=params, headers=headers) as resp:
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client.py", line 1138, in __aenter__
self._resp = await self._coro
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client.py", line 507, in _request
req = self._request_class(
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 313, in __init__
self.update_body_from_data(data)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 512, in update_body_from_data
body = FormData(body)()
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 170, in __call__
return self._gen_form_data()
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 149, in _gen_form_data
raise TypeError(
TypeError: Can not serialize value type: <class 'tuple'>
headers: {}
value: ('metadata', '{"name": "COCO_train2014_000000000061.jpg", "parents": [null]}', 'application/json; charset=UTF-8')
Task exception was never retrieved
future: <Task finished name='Task-3' coro=<upload_file() done, defined at C:/Git/GoogleDriveAPI/googledriveapi_async.py:41> exception=TypeError('Can not serialize value type: <class \'tuple\'>\n headers: {}\n value: (\'metadata\', \'{"name": "COCO_train2014_000000000049.jpg", "parents": [null]}\', \'application/json; charset=UTF-8\')')>
Traceback (most recent call last):
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 510, in update_body_from_data
body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 118, in get
raise LookupError()
aiohttp.payload.LookupError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 145, in _gen_form_data
part = payload.get_payload(
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 71, in get_payload
return PAYLOAD_REGISTRY.get(data, *args, **kwargs)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\payload.py", line 118, in get
raise LookupError()
aiohttp.payload.LookupError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:/Git/GoogleDriveAPI/googledriveapi_async.py", line 65, in upload_file
async with session.post(url, data=data, params=params, headers=headers) as resp:
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client.py", line 1138, in __aenter__
self._resp = await self._coro
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client.py", line 507, in _request
req = self._request_class(
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 313, in __init__
self.update_body_from_data(data)
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\client_reqrep.py", line 512, in update_body_from_data
body = FormData(body)()
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 170, in __call__
return self._gen_form_data()
File "C:\VirtualEnv\basic\lib\site-packages\aiohttp\formdata.py", line 149, in _gen_form_data
raise TypeError(
TypeError: Can not serialize value type: <class 'tuple'>
headers: {}
value: ('metadata', '{"name": "COCO_train2014_000000000049.jpg", "parents": [null]}', 'application/json; charset=UTF-8')
Process finished with exit code 1
uj5u.com熱心網友回復:
當我看到您的腳本時,我認為為了multipart/form-data使用您的腳本進行請求,需要創建請求正文。我認為這可能是您的問題的原因。當這反映在您的腳本中時,它變為如下。
從:
data = {
"MetaData": (
"metadata",
json.dumps(file_metadata),
"application/json; charset=UTF-8",
),
"Media": open(file_path, "rb"),
}
global token
headers = {"Authorization": "Bearer {}".format(token)}
params = {"uploadType": "multipart"}
async with session.post(url, data=data, params=params, headers=headers) as resp:
print(resp.text)
至:
data = aiohttp.FormData()
data.add_field(
"metadata",
json.dumps(file_metadata),
content_type="application/json; charset=UTF-8",
)
data.add_field("file", open(file_path, "rb"))
global token
headers = {"Authorization": "Bearer {}".format(token)}
params = {"uploadType": "multipart"}
async with session.post(url, data=data, params=params, headers=headers) as resp:
r = await resp.json()
print(r)
測驗:
運行此修改后的腳本時,將獲得以下結果。
{'kind': 'drive#file', 'id': '###', 'name': '###', 'mimeType': '###'}
,
,
,
筆記:
- 此修改后的腳本假設您的訪問令牌可用于將檔案上傳到 Google Drive。請注意這一點。
參考:
- 發布 aiohttp 的多部分編碼檔案
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/487507.html
標籤:Python http 邮政 谷歌驱动API aiohttp
