将文件上传到 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(),它支持 bytesstring 格式的 data。例如:

blob.upload_from_string(file.file.read())

或者,由于您使用 async def 定义了端点(请参阅 了解 defasync 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(这意味着它将等待连接关闭)。