クラウド ストレージ バケットから 5 つの基本的なテキスト ファイルを読み取り、圧縮して、BlobStore に書き込もうとしています。
from google.appengine.api import files
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
import StringIO
import zipfile
class FactoryHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self):
""" SERVE THE BLOB, IF KEY AVAILABLE """
k = self.request.get('key')
if k:
self.send_blob(k)
return
""" TAKES FROM CLOUD STORAGE , ZIPS IT """
zipstream = StringIO.StringIO()
zfile = zipfile.ZipFile(file=zipstream, mode='w')
objects = files.listdir('/gs/test-bucket')
for o in objects:
with files.open(o, 'r') as f:
data = f.read(1)
while data != "":
zfile.writestr(o.encode('utf-8'),data)
data = f.read(1)
zfile.close()
zipstream.seek()
""" NOW, ADD ZIP TO BLOBSTORE """
zip_file = files.blobstore.create(mime_type='application/zip',_blobinfo_uploaded_filename='test.zip')
zip_data = zipstream.getvalue()
with files.open(zip_file, 'a') as f:
f.write(zip_data)
files.finalize(zip_file)
blob_key = files.blobstore.get_blob_key(zip_file)
self.response.out.write(blob_key)
どういうわけか、私はいつも各テキスト ファイルの最後の文字だけになってしまいます。を呼び出しているためだと思いf.read(1)
ますが、コードは基本的に各バイトを反復処理してから、zfile
オブジェクトに書き込みます。
データを連結してみました:
for o in objects:
with files.open(o, 'r') as f:
data = f.read(1)
while data != "":
data += f.read(1)
""" once completed, write """
zfile.writestr(o.encode('utf-8'),data)
しかし、App Engine 開発サーバーがハングします。おそらく、データを連結できないためです。
解決策はありますか?これはテキスト以外のファイルでも機能しますか? (画像、mp3 など)
編集:
そのため、実稼働アプリ + Google ストレージ アカウントで回答を実行しました。
このエラーが発生しました
ApplicationError: 8
Traceback (most recent call last):
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/_webapp25.py", line
710, in __call__
handler.get(*groups)
File "/base/data/home/apps/s~app-name/v1-55-app-
proto.363439297871242967/factory.py", line 98, in get
with files.open(o, 'r') as f:
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 520,
in open
exclusive_lock=exclusive_lock)
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 276,
in __init__
self._open()
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 423,
in _open
self._make_rpc_call_with_retry('Open', request, response)
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 427,
in _make_rpc_call_with_retry
_make_call(method, request, response)
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 252,
in _make_call
_raise_app_error(e)
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 210,
in _raise_app_error
raise PermissionDeniedError(e)
PermissionDeniedError: ApplicationError: 8
私の ACL 設定は正しかった (以前に ACL Access Denied Error を取得して修正した)
元の設定に追加された ACL 設定、バケット固有
<Entry>
<Scope type="UserByEmail">
<EmailAddress>
app-name@appspot.gserviceaccount.com
</EmailAddress>
</Scope>
<Permission>
FULL_CONTROL
</Permission>
</Entry>
ヒントはありますか?https://developers.google.com/appengine/docs/python/googlestorage/exceptionsのドキュメントによると
exception PermissionDeniedError()
The application does not have permission to perform this operation.
更新 - ファイルを public_read に設定すると、アプリを介してファイルを読み取ることができることに気付きました。これは、私のアプリがプライベート モードでアクセスするように適切に構成されていないことを意味します。ヒントはありますか?(私が知っている)それを修正する唯一の方法はACLを使用することであり、私はすでにその部分を構成しています。