文件未以实际名称 Flask 和 Google 云存储下载

问题描述

我正在构建一个 Flask 应用程序,该应用程序具有从谷歌云存储上传和下载文件功能。对于下载部分,我已经实现了以下代码

def downloadBlob(filename):
    storage_client = storage.Client(project=local_constants.PROJECT_NAME) # my project name here
    bucket = storage_client.bucket(local_constants.PROJECT_STORAGE_BUCKET) # bucket here
    blob = bucket.blob(filename)
    return blob.download_as_bytes()

我正在使用这段代码调用这个函数

return Response(downloadBlob(cur_user['root_directory']+cur_dir+file_name),mimetype='application/octet-stream')

其中 cur_user['root_directory'] 是每个用户不同的 63 位随机数,cur_dir 是 63 位随机数后的文件路径,file_name用户选择的文件下载。

路径示例为 4223099317976595278/test.txt。这意味着 4223099317976595278用户的根目录,/ 是 cur_dir,text.txt文件名。

我面临的问题是我的文件自动重命名download_file。我尝试将函数 blob.download_as_bytes() 更改为 blob.download_to_filename(),但它对我也不起作用。

如果文件位于云存储的根目录中,它们将获得正确的名称,如果文件位于其他文件夹中,则会发生上述问题。

有人能指出错误或建议我解决这个问题吗?

解决方法

您需要告诉浏览器您想要的文件名。为此,您需要添加一个名为 Content-Disposition 的标头(例如)

return Response(downloadBlob(cur_user['root_directory']+cur_dir+file_name),mimetype='application/octet-stream',headers={"Content-Disposition": "filename="+file_name})
,

感谢@guillaume blaquire 提供答案,我进一步搜索了该问题并获得了一些相关信息。

函数download_as_bytes()download_as_string() 尝试下载具有实际名称的文件。这两个功能都适用于存在于云存储根目录中的文件。例如同一文件在云存储中不同位置的路径为:

  1. file.txt(文件位于云存储的根目录中。
  2. some_folder/some_other_folder/file.txt(文件存在于内部目录中)

情况1,文件名是file.txt,但情况2,文件名是some_folder/some_other_folder/file.txt,当我们尝试下载情况1中的文件时,它将按原样命名。但在情况 2 中,文件名将更改为 download_file,因为 / 是文件名中的非法字符。

因此,我们必须在下载文件时使用 Content-Disposition 标头为我们的文件指定一个特定名称。

得出结论,而不是使用此代码:

return Response(downloadBlob(cur_user['root_directory']+cur_dir+file_name),mimetype='application/octet-stream')

我应该使用这个代码。

return Response(downloadBlob(cur_user['root_directory']+cur_dir+file_name),headers={"Content-Disposition": "filename="+file_name})