Я планирую создать веб-приложение, которое позволит пользователям переходить на более раннюю версию своих файлов проектов Visual Studio. Однако похоже, что Google App Engine принимает загрузку файлов и хранение плоских файлов на сервере Google через db.TextProperty и db.BlobProperty.
Я буду рад, что кто-нибудь может предоставить образец кода (как на стороне клиента, так и на стороне сервера) о том, как это можно сделать.






Вы не можете хранить файлы, так как нет традиционной файловой системы. Вы можете хранить их только в их собственном хранилище данных (в поле, определенном как BlobProperty)
В предыдущей ссылке есть пример:
class MyModel(db.Model):
blob = db.BlobProperty()
obj = MyModel()
obj.blob = db.Blob( file_contents )
В Google App Engine нет хранения плоских файлов. Все должно идти в Хранилище данных, который немного похож на реляционную базу данных, но не совсем.
Вы можете хранить файлы как атрибуты TextProperty или BlobProperty.
Для записей в хранилище данных существует ограничение в 1 МБ, что может быть проблемой, а может и не быть.
Как сохранить файлы размером более 1мб. Я использую github.com/ckopanos/django-google-cloud-storage
Об этом есть ветка в группах Google:
С большим количеством полезного кода это обсуждение очень помогло мне в загрузке файлов.
Фактически, ответ на этот вопрос содержится в документации App Engine. См. Пример на Загрузка пользовательских изображений.
HTML-код внутри <form> </form>:
<input type = "file" name = "img"/>
Код Python:
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get("content")
avatar = self.request.get("img")
greeting.avatar = db.Blob(avatar)
greeting.put()
self.redirect('/')Не нравится этот подход, потому что вы теряете информацию о типе пантомимы.
@santiagobasulto: Почему бы тебе самому не проверить это?
Я не хочу это проверять. Когда вам нужно отобразить изображение, вы должны предоставить информацию о типе MIME (будь то изображение JPG, GIF и т. д.), Поэтому вы должны предоставить HTTP-заголовок типа контента. Если вы загрузите изображение с помощью предоставленного вами решения, то в будущем вы не будете знать тип содержимого изображения, следовательно, вы не можете установить заголовок, следовательно, старые странные браузеры будут иметь проблемы с отображением изображения ( из-за отсутствия типа контента)
Если вы не проверяете тип MIME, которому доверяете клиент, оставляя вас уязвимым для атак типа «черная шляпа» или неверно настроенных типов MIME в клиенте. Если вы собираетесь это сделать, вы можете просто доверять самому расширению файла.
Если проблема не исчезла, убедитесь, что вы используете enctype в теге формы.
Нет:
<form encoding = "multipart/form-data" action = "/upload">
Да:
<form enctype = "multipart/form-data" action = "/upload">
Я получал ошибку кодирования, прежде чем реализовал ваш ответ
Когда я делал это, меня действительно раздражала проблема отсутствия «размера» для типа ввода файла. Я тестировал Safari, который, по-видимому, имеет очень короткую длину файла по умолчанию (?), И все, что я получал в GAE для содержимого файла, это имя файла. Просто слово предупреждения, которое может спасти кого-то от небольшой головной боли.
Лично я считаю, что учебник, описывающий здесь, полезен при использовании среды выполнения Java с GAE. По какой-то причине, когда я пытался загрузить файл с помощью
<form action = "/testservelet" method = "get" enctype = "multipart/form-data">
<div>
Myfile:<input type = "file" name = "file" size = "50"/>
</div>
<div>
<input type = "submit" value = "Upload file">
</div>
</form>
Я обнаружил, что мой класс HttpServlet по какой-то причине не принимает форму с атрибутом enctype. Однако удаление работает, это означает, что я не могу загружать файлы.
Это может быть потому, что вы используете метод get, попробуйте вместо этого настроить его на публикацию. Я не уверен, что это сработает, но попробовать стоит.
Google выпустила сервис для хранения больших файлов. Взгляните на документация по API blobstore. Если размер ваших файлов> 1 МБ, вам следует его использовать.
Как сохранять файлы> 1мб. Я использую github.com/ckopanos/django-google-cloud-storage
Пробую сегодня, работает он следующим образом:
моя версия sdk - 1.3.x
html-страница:
<form enctype = "multipart/form-data" action = "/upload" method = "post" >
<input type = "file" name = "myfile" />
<input type = "submit" />
</form>
Код сервера:
file_contents = self.request.POST.get('myfile').file.read()
Я заметил странное поведение при загрузке файлов в App Engine. Когда вы отправляете следующую форму:
<form method = "post" action = "/upload" enctype = "multipart/form-data">
<input type = "file" name = "img" />
...
</form>
Затем вы извлекаете img из запроса следующим образом:
img_contents = self.request.get('img')
Переменная img_contents - это str() в Google Chrome, но в Firefox - это Unicode. И как вы сейчас, конструктор db.Blob() принимает строку и выдаст ошибку, если вы передадите строку в Юникоде.
Кто-нибудь знает, как это можно исправить?
Кроме того, что мне кажется совершенно странным, так это то, что когда я копирую и вставляю приложение «Гостевая книга» (с аватарами), оно работает отлично. Я делаю все точно так же в своем коде, но это просто не сработает. Я очень близок к тому, чтобы выдернуть волосы.
: D В форме говорилось: multipart / form-data вместо multipart / form-data. Chrome достаточно умен, чтобы исправить опечатку, а Firefox - нет.
Вот полный рабочий файл. Я взял оригинал с сайта Google и изменил его, чтобы сделать его немного более реальным.
Обратите внимание на несколько вещей:
Назначение этой строки в Класс ServeHandler предназначен для "исправления" ключ, чтобы он избавился от любого имени искажение, которое могло произойти в браузер (в Хром)
blob_key = str(urllib.unquote(blob_key))
Предложение "save_as" в конце этого очень важно. Он будет следить за тем, чтобы имя файла не искажалось при отправке в ваш браузер. Избавьтесь от него и понаблюдайте за тем, что происходит.
self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)
Удачи!
import os
import urllib
from google.appengine.ext import blobstore
from google.appengine.ext import webapp
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
class MainHandler(webapp.RequestHandler):
def get(self):
upload_url = blobstore.create_upload_url('/upload')
self.response.out.write('<html><body>')
self.response.out.write('<form action = "%s" method = "POST" enctype = "multipart/form-data">' % upload_url)
self.response.out.write("""Upload File: <input type = "file" name = "file"><br> <input type = "submit" name = "submit" value = "Submit"> </form></body></html>""")
for b in blobstore.BlobInfo.all():
self.response.out.write('<li><a href = "/serve/%s' % str(b.key()) + '">' + str(b.filename) + '</a>')
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
upload_files = self.get_uploads('file')
blob_info = upload_files[0]
self.redirect('/')
class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self, blob_key):
blob_key = str(urllib.unquote(blob_key))
if not blobstore.get(blob_key):
self.error(404)
else:
self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)
def main():
application = webapp.WSGIApplication(
[('/', MainHandler),
('/upload', UploadHandler),
('/serve/([^/]+)?', ServeHandler),
], debug=True)
run_wsgi_app(application)
if __name__ == '__main__':
main()
Удивительно, что это работает для всех, кроме меня ... self.__uploads в blobstore_handler - это None, когда я пробую это.
Есть способ использовать плоская файловая система (по крайней мере, с точки зрения использования)
Есть этот Проект виртуальной файловой системы Google App Engine. который реализован с помощью API хранилища данных и кэша памяти для имитации обычной файловой системы. Используя эту библиотеку, вы можете использовать в своем проекте аналогичный доступ к файловой системе (чтение и запись).
@ user858915 Ссылка битая :(