Google Cloud Storage含Unicode字符的Blob签名URL生成失败
Google Cloud Storage生成签名URL时Unicode文件名触发KeyError的解决方案
问题场景
测试GCS上传下载功能时,Blob名称仅含英文、空格或常规特殊字符时,生成签名URL正常;但使用包含Unicode字符(如阿拉伯语文件名جراج.png)时,触发KeyError: u'\u062c'错误。官方文档明确说明Blob名称支持任意有效Unicode序列(UTF-8编码后1-1024字节)。
相关代码
generate_download_signed_url_v4("storage_files", "202209/جراج.png") def generate_download_signed_url_v4(bucket_name, blob_name): storage_client = storage.Client.from_service_account_json('s_account.json') bucket = storage_client.bucket(bucket_name) blob = bucket.blob(blob_name) url = blob.generate_signed_url( expiration=datetime.timedelta(minutes=10), # URL有效期10分钟 method="GET", # 允许GET请求 ) print "Generated GET signed URL:", url return url
报错栈
Traceback (most recent call last): File "/Users/k/Documents/app30/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__ rv = self.router.dispatch(request, response) File "/Users/k/Documents/app30/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher return route.handler_adapter(request, response) File "/Users/k/Documents/app30/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__ return handler.dispatch() File "/Users/k/Documents/app30/gae/users_app/helpers.py", line 68, in dispatch webapp2.RequestHandler.dispatch(self) # dispatch the main handler File "/Users/k/Documents/app30/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 572, in dispatch return self.handle_exception(e, self.app.debug) File "/Users/k/Documents/app30/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 570, in dispatch return method(*args, **kwargs) File "/Users/k/Documents/app30/gae/users_app/helpers.py", line 431, in check_admin return myfunction(self, *args, **kwargs) File "/Users/k/Documents/app30/gae/users_app/main.py", line 10796, in get my_file_link = self.generate_download_signed_url_v4(root_bucket_name, "572680296//202209/جراج.png") File "/Users/k/Documents/app30/gae/users_app/main.py", line 10863, in generate_download_signed_url_v4 method="GET", # Allow GET requests using this URL. File "/Users/k/Documents/app30/gae/users_app/lib/google/cloud/storage/blob.py", line 338, in generate_signed_url quoted_name=quote(self.name)) File "/Users/k/Documents/app30/google-cloud-sdk/platform/google_appengine/google/appengine/dist27/urllib.py", line 1294, in quote return ''.join(map(quoter, s)) KeyError: u'\u062c' *******> Exception: u'\u062c'
当前使用本地开发服务器版本v.340。
原因分析
报错根源是Python 2.7环境下App Engine内置的urllib.quote函数不支持直接处理Unicode字符串,遇到非ASCII Unicode字符时会抛出KeyError。GCS客户端库生成签名URL时,内部调用了该旧版quote方法,导致编码失败。
修复方案
手动对Unicode格式的Blob名称进行UTF-8编码,再传入签名URL生成逻辑,或直接指定编码后的quoted_name参数覆盖内部处理:
修改后的代码
from urllib import quote import datetime from google.cloud import storage generate_download_signed_url_v4("storage_files", "202209/جراج.png") def generate_download_signed_url_v4(bucket_name, blob_name): storage_client = storage.Client.from_service_account_json('s_account.json') bucket = storage_client.bucket(bucket_name) # 将Unicode文件名转换为UTF-8字节串,兼容旧版urllib处理 blob_name_utf8 = blob_name.encode('utf-8') blob = bucket.blob(blob_name_utf8) # 手动生成URL编码后的文件名,避免内部调用报错的quote方法 quoted_name = quote(blob_name_utf8) url = blob.generate_signed_url( expiration=datetime.timedelta(minutes=10), method="GET", quoted_name=quoted_name # 传入手动编码的文件名 ) print "Generated GET signed URL:", url return url
说明
- 先将Unicode类型的Blob名称编码为UTF-8字节串,确保旧版
urllib.quote能正确处理; - 通过
quoted_name参数手动传入编码后的文件名,绕过客户端库内部可能出错的编码逻辑; - 该方案适配Python 2.7 + App Engine本地服务器v340的环境,同时符合GCS对Unicode文件名的支持规范。
内容的提问来源于stack exchange,提问作者Khaled
相关产品推荐
相关产品推荐

