gpt4 book ai didi

python - 使用 google-api-client 使用存储在内存中的 flask/python 中的可恢复上传将大文件从客户端上传到 GDrive

转载 作者:行者123 更新时间:2023-12-04 04:10:50 28 4
gpt4 key购买 nike

我正在尝试使用 google-api-client 将大文件上传到 gdrive。我正在使用可恢复上传。这里的问题是我不想在我的文件系统中保存/写入文件对象。我希望它以 block 的形式读取它,因此使用可恢复上传将相同的 block 上传到 Gdrive。无论如何,在我可以通过 google api python 客户端发送 block 的地方可以实现这一点。

这是我的示例代码,它可以工作,但它从客户端获取整个文件对象。

@app.route('/upload', methods = ["GET", "POST"])
def upload_buffer():
drive = cred()
if request.method == "POST":
mime_type = request.headers['Content-Type']
body = {
'name': "op.pdf",
'mimeType': mime_type,
}

chunk = BytesIO(request.stream.read()) # as you can see here the entire file stream is obtained

#I want to read in chunks and simultaneously send that chunk to GDrive

#chunk = BytesIO(request.stream.read(1024))

#if I send like the above only some part of the file is uploaded in Gdrive

media_body = MediaIoBaseUpload(chunk, chunksize = 1024, mimetype=mime_type,
resumable=True)

return drive.files().create(body=body,
media_body=media_body,
fields='id,name,mimeType,createdTime,modifiedTime').execute()

return render_template("upload_image.html")

<-------------------------------------------- ---------------------->这就是我使用 Google Rest API 的方式

@app.route('/upload3', methods=["GET", "POST"])
def upload_buff():

if request.method == "POST":
Content_Length = request.headers['Content-Length']

access_token = '####'

headers = {"Authorization": "Bearer " + access_token, "Content-Type": "application/json", "Content-Length": Content_Length}
params = {
"name": "file_name.pdf",
"mimeType": "application/pdf"
}
r = requests.post("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable", headers=headers, data=json.dumps(params))

location = r.headers['Location']
print("----------------------------------------------------")
print("GDrive Upload url : ", location)
print("----------------------------------------------------")

start = str(0)
while True:
chunk = request.stream.read(1024 * 1024)
chunk_size = len(chunk)
print("----------------------------------------------------")
print("Size of Received Chunk From Client: ", chunk_size)
print("----------------------------------------------------")
if chunk_size == 0:
break
end = str(int(start)+chunk_size-1)
headers = {'Content-Range': 'bytes '+start+'-' + end + '/' +str(Content_Length), 'Content-Length': str(chunk_size)}
start = str(int(end)+1)
print("The headers set for the chunk upload : ", headers)
r = requests.put(location, headers=headers, data=chunk)
print("----------------------------------------------------")
print("Response content : ", r.content)
print("Response headers : ", r.headers)
print("Response status : ", r.status_code)
print("----------------------------------------------------")
return r.content

return render_template("upload_image.html")

最佳答案

阅读您的问题和代码,我假设您将流保存在一个名为 chunk 的变量中,并希望将其分成 1024 字节的 block 以使用 resumable upload .如果我对问题的理解是正确的,你可以在 bytes object 中使用切片。 chunk 以类似于此的方式:

chunk = b"\x04\x09\x09\x01\x01\x01\x00\x03" # Example values
chunk[:3] # Equals to b"\x04\x09\x09"
chunk[-3:] # Equals to b"\x01\x00\x03"
chunk[4:2] # Equals to b"\x01\x01"

您可以使用这种方法将 chunk 分成 1024 字节的片段。如果您需要更多帮助,请问我任何问题。


对于我对您问题的错误理解,我深表歉意。我现在了解到您有一个字节对象,分为多个 block ,并希望使用可恢复上传将其上传到云端硬盘。如果我的实际假设是正确的,您可以使用我为该场景编写的代码。使用此代码,无需在硬盘上写入任何内容。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import locale
import requests
import sys
from io import BytesIO

accessToken = \
'{YOUR ACCESS TOKEN HERE}'
fileData = \
BytesIO(requests.get('https://upload.wikimedia.org/wikipedia/commons/c/cf/Alhambra_evening_panorama_Mirador_San_Nicolas_sRGB-1.jpg'
).content).getvalue()
fileSize = sys.getsizeof(fileData) - 129

# Step I - Chop data into chunks
wholeSize = fileSize
chunkSize = 4980736 # Almost 5 MB
chunkTally = 0
chunkData = []
while wholeSize > 0:
if (chunkTally + 1) * chunkSize > fileSize:
chunkData.append(fileData[chunkTally * chunkSize:fileSize])
else:
chunkData.append(fileData[chunkTally * chunkSize:(chunkTally
+ 1) * chunkSize])
wholeSize -= chunkSize
chunkTally += 1

# Step II - Initiate resumable upload
headers = {'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/json'}
parameters = {'name': 'alhambra.jpg',
'description': 'Evening panorama of Alhambra from Mirador de San Nicol\xc3\xa1s, Granada, Spain.'}
r = \
requests.post('https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable'
, headers=headers, data=json.dumps(parameters))
location = r.headers['location']

# Step III - File upload
chunkTally = 0
for chunk in chunkData:
if (chunkTally + 1) * chunkSize - 1 > fileSize - 1:
finalByte = fileSize - 1
chunkLength = fileSize - chunkTally * chunkSize
else:
finalByte = (chunkTally + 1) * chunkSize - 1
chunkLength = chunkSize
headers = {'Content-Length': str(chunkLength),
'Content-Range': 'bytes ' + str(chunkTally * chunkSize) \
+ '-' + str(finalByte) + '/' + str(fileSize)}
r = requests.put(location, headers=headers, data=chunk)
print(r.text) # Response
chunkTally += 1

例如,此脚本将采用 photo来自维基共享资源;您可以改用文件流。获取数据后,代码将根据变量使用的内存空间计算文件大小(因为它没有写入硬盘)。

下一步是将文件分成小于 5 MB 的 block 。我确保使用 1024*256 的倍数,详见 docs .数据将被迭代,直到它被分成几乎 5 MB 的 block (除了最后一个)。

在该操作之后,代码会将可恢复上传初始化为 documented使用 OAuth 2.0用于身份验证。在此步骤中,我为我的文件使用了一些示例元数据,但您可以继续阅读 Files properties关于其他的。最后,脚本会将位置保存在一个变量中以备将来上传。

在最后一步中, block 将被迭代并一个一个地上传。首先,一个标题是基于 specifications 构建的.之后,我们已经准备好 header 、 block 和上传位置,因此我们可以继续在请求中正式上传。上传每个 block 后,将打印响应以记录错误,并在最后一个 block 之后显示上传文件的元数据。这标志着整个操作的结束。作为最后的说明,我想提一下我是在 Python3 中编写和测试这个脚本的。如果您有任何疑问,请随时向我寻求澄清。

关于python - 使用 google-api-client 使用存储在内存中的 flask/python 中的可恢复上传将大文件从客户端上传到 GDrive,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61757978/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com