2

我发现了一个错误,如下所示。

INFO     ~ module.py:639] default: "HEAD /_ah/gcs/app_default_bucket/multibytes.txt HTTP/1.1" 404 -
ERROR    ~ gcs.py:99] Expect status [200] from Google Storage. But got status 404.
Path: '/app_default_bucket/multibytes.txt'.
Request headers: None.
Response headers: {'date': 'Mon, 07 Jul 2014 12:59:44 GMT', 'server': 'Development/2.0', 'connection': 'close'}.
Body: ''.
Extra info: None.
Traceback (most recent call last):
  File "/gcs.py", line 97, in status
        stat = gcs.stat("/%s/%s" % (b,nm))
  File "/cloudstorage/cloudstorage_api.py", line 142, in stat
        body=content)
  File "/cloudstorage/errors.py", line 132, in check_status
        raise NotFoundError(msg)
NotFoundError: Expect status [200] from Google Storage. But got status 404.
Path: '/app_default_bucket/multibytes.txt'.
Request headers: None.
Response headers: {'date': 'Mon, 07 Jul 2014 12:59:44 GMT', 'server': 'Development/2.0', 'connection': 'close'}.
Body: ''.
Extra info: None.

例如,这是我的自定义 GCS 客户端类。

# encoding: utf-8

import cloudstorage as gcs

class mycustomgcsclient:

  #...

  def create(self,name,data,**options):
    options['retry_params'] = gcs.RetryParams(backoff_factor=1.1)

    if not options.get('content_type'):
      options['content_type'] = 'octet-stream'

    if isintance(name,unicode):
      name = name.encode('utf-8')

    path = '/mybucketname/%s' % name
    try:
      with gcs.open(path,'w',**options) as f:
        f.write(data)
      return True
    except Exception as e:
      logging.exception(e)

    return False

if __name__=='__main__':
  data = 'some data ...¥n'

  filename = 'somedir/%s' % u'sample.txt'
  mycustomgcsclient().create(filename,data) # no error occured.

  filename = 'somedir/%s' % u'あいうえお.txt'
  mycustomgcsclient().create(filename,data) # error occured in this line.

仅使用多字节文件名时,我在上面发现了一个错误。

使用 ascii 的文件名时,我没有发现任何错误。

我正在使用https://developers.google.com/appengine/docs/python/googlecloudstorageclient/download上提供的“GCS 客户端库(Python)” 。

我的 dev_appserver.py 版本是 Development SDK 1.9.6,这适用于 MacOS X Marve ..(?忘记了)。

有一些解决方案吗?

4

1 回答 1

3

我认为您可能需要urllib.quote()在将其编码为 utf8 后调用该名称。

这是 GCS Python 演示 ( http://appengine-gcs-client.googlecode.com/svn/trunk/python/demo/main.py ) 的修改版本,它使用多字节文件名可以正常工作:

# Copyright 2012 Google Inc. All Rights Reserved.
# encoding: utf-8

"""A modified version of the sample app that uses GCS client to operate on
   bucket and file.
"""

import logging
import os
import cloudstorage as gcs
import webapp2
import urllib

from google.appengine.api import app_identity

my_default_retry_params = gcs.RetryParams(initial_delay=0.2,
                                          max_delay=5.0,
                                          backoff_factor=2,
                                          max_retry_period=15)
gcs.set_default_retry_params(my_default_retry_params)


class MainPage(webapp2.RequestHandler):
  """Main page for GCS demo application."""

  def get(self):
    bucket_name = os.environ.get('BUCKET_NAME',
                                 app_identity.get_default_gcs_bucket_name())

    self.response.headers['Content-Type'] = 'text/plain'
    self.response.write('Demo GCS Application running from Version: '
                        + os.environ['CURRENT_VERSION_ID'] + '\n')
    self.response.write('Using bucket name: ' + bucket_name + '\n\n')

    bucket = '/' + bucket_name
    filename = bucket + '/' + urllib.quote(u'あいうえお.txt'.encode('utf8'))
    self.tmp_filenames_to_clean_up = []

    try:
      self.create_file(filename)
      self.response.write('\n\n')

      self.read_file(filename)
      self.response.write('\n\n')

    except Exception, e:
      logging.exception(e)
      self.delete_files()
      self.response.write('\n\nThere was an error running the demo! '
                          'Please check the logs for more details.\n')

    else:
      self.delete_files()
      self.response.write('\n\nThe demo ran successfully!\n')

  def create_file(self, filename):
    """Create a file.

    The retry_params specified in the open call will override the default
    retry params for this particular file handle.

    Args:
      filename: filename.
    """
    self.response.write('Creating file %s\n' %
                        urllib.unquote(filename).decode('utf-8'))

    write_retry_params = gcs.RetryParams(backoff_factor=1.1)
    gcs_file = gcs.open(filename,
                        'w',
                        content_type='text/plain',
                        options={'x-goog-meta-foo': 'foo',
                                 'x-goog-meta-bar': 'bar'},
                        retry_params=write_retry_params)
    gcs_file.write('some data ...¥n\n')
    gcs_file.close()
    self.tmp_filenames_to_clean_up.append(filename)


  def read_file(self, filename):
    self.response.write('File Content:\n')

    gcs_file = gcs.open(filename)
    self.response.write(gcs_file.readline())
    gcs_file.close()

  def delete_files(self):
    self.response.write('Deleting files...\n')
    for filename in self.tmp_filenames_to_clean_up:
      self.response.write('Deleting file %s\n' %
                          urllib.unquote(filename).decode('utf-8'))
      try:
        gcs.delete(filename)
      except gcs.NotFoundError:
        pass

app = webapp2.WSGIApplication([('/', MainPage)],
                              debug=True)
于 2014-07-08T22:49:36.520 回答