将文件上传到 google 云存储时出错
Error uploading file to google cloud storage
如何将我服务器上的文件上传到google云存储?
下面给出了我试过的代码,但是,它抛出一个类型错误,说,预期的类型不是字节:
the expected type is not byte for:
blob.upload_from_file(file.file.read()).
尽管upload_from_file需要二进制类型。
@app.post("/file/")
async def create_upload_file(files: List[UploadFile] = File(...)):
storage_client = storage.Client.from_service_account_json(path.json)
bucket_name = 'data'
try:
bucket = storage_client.create_bucket(bucket_name)
except Exception:
bucket = storage_client.get_bucket(bucket_name)
for file in files:
destination_file_name = f'{file.filename}'
new_data = models.Data(
path=destination_file_name
)
try:
blob = bucket.blob(destination_file_name)
blob.upload_from_file(file.file.read())
except Exception:
raise HTTPException(
status_code=500,
detail="File upload failed"
)
选项 1
根据文档,upload_from_file()
supports a file-like object; hence, you could use the .file
attribute of UploadFile
(which represents a SpooledTemporaryFile 实例)。例如:
blob.upload_from_file(file.file)
选项 2
您可以读取 file
的内容并将它们传递给 upload_from_string()
,它支持 bytes
或 string
格式的 data
。例如:
blob.upload_from_string(file.file.read())
或者,由于您使用 async def
定义了端点(请参阅 了解 def
与 async def
):
contents = await file.read()
blob.upload_from_string(contents)
选项 3
为了完整起见,upload_from_filename()
expects a filename
which represents the path to the file
. Hence, the No such file or directory
error was thrown when you passed file.filename
(as mentioned in your comment), as this is not a path to the file. To use that method (as a last resort), you should save the file
contents to a NamedTemporaryFile
,它“在文件系统中有一个可见的名称”,“可以用来打开文件”,一旦你用完了,就把它删除。示例:
from tempfile import NamedTemporaryFile
import os
contents = await file.read() # or, contents = file.file.read()
temp = NamedTemporaryFile(delete=False)
try:
with temp as f:
f.write(contents);
blob.upload_from_filename(temp.name)
finally:
temp.close()
os.unlink(temp.name)
注:
如果您要将相当大的文件上传到 Google 云存储,可能需要一些时间才能完全上传,并且遇到 timeout
错误,请考虑增加 通过更改 timeout
值,等待服务器响应 的时间量,例如 upload_from_file()
中所示 - 默认设置为 timeout=60
秒。要更改它,请使用例如 blob.upload_from_file(file.file, timeout=180)
,或者您也可以设置 timeout=None
(这意味着它将等待连接关闭)。
如何将我服务器上的文件上传到google云存储?
下面给出了我试过的代码,但是,它抛出一个类型错误,说,预期的类型不是字节:
the expected type is not byte for:
blob.upload_from_file(file.file.read()).
尽管upload_from_file需要二进制类型。
@app.post("/file/")
async def create_upload_file(files: List[UploadFile] = File(...)):
storage_client = storage.Client.from_service_account_json(path.json)
bucket_name = 'data'
try:
bucket = storage_client.create_bucket(bucket_name)
except Exception:
bucket = storage_client.get_bucket(bucket_name)
for file in files:
destination_file_name = f'{file.filename}'
new_data = models.Data(
path=destination_file_name
)
try:
blob = bucket.blob(destination_file_name)
blob.upload_from_file(file.file.read())
except Exception:
raise HTTPException(
status_code=500,
detail="File upload failed"
)
选项 1
根据文档,upload_from_file()
supports a file-like object; hence, you could use the .file
attribute of UploadFile
(which represents a SpooledTemporaryFile 实例)。例如:
blob.upload_from_file(file.file)
选项 2
您可以读取 file
的内容并将它们传递给 upload_from_string()
,它支持 bytes
或 string
格式的 data
。例如:
blob.upload_from_string(file.file.read())
或者,由于您使用 async def
定义了端点(请参阅 def
与 async def
):
contents = await file.read()
blob.upload_from_string(contents)
选项 3
为了完整起见,upload_from_filename()
expects a filename
which represents the path to the file
. Hence, the No such file or directory
error was thrown when you passed file.filename
(as mentioned in your comment), as this is not a path to the file. To use that method (as a last resort), you should save the file
contents to a NamedTemporaryFile
,它“在文件系统中有一个可见的名称”,“可以用来打开文件”,一旦你用完了,就把它删除。示例:
from tempfile import NamedTemporaryFile
import os
contents = await file.read() # or, contents = file.file.read()
temp = NamedTemporaryFile(delete=False)
try:
with temp as f:
f.write(contents);
blob.upload_from_filename(temp.name)
finally:
temp.close()
os.unlink(temp.name)
注:
如果您要将相当大的文件上传到 Google 云存储,可能需要一些时间才能完全上传,并且遇到 timeout
错误,请考虑增加 通过更改 timeout
值,等待服务器响应 的时间量,例如 upload_from_file()
中所示 - 默认设置为 timeout=60
秒。要更改它,请使用例如 blob.upload_from_file(file.file, timeout=180)
,或者您也可以设置 timeout=None
(这意味着它将等待连接关闭)。