SAE禁止本地IO,所以上传文件必须使用Storage服务。
(1)首先启动Storage服务,设置一个Domain名字,例如
files:
(2)然后在setting文件中修改
MEDIA_ROOT:’http://project-Domain.stor.sinaapp.com/’
(3)继承sae.storage里的FileSystemStorage类,根据需求重写里面的方法, 注意save方法中要写Domain的文字:
from django.utils.translation import ugettext as _
from django.core.files.storage import FileSystemStorage
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.conf import settings import time,os,uuid,random,unicodedata,StringIO
from django.core.files.base import ContentFile
import sae
import tempfile
import sae.storage
from PIL import Image
class SaeAndNotSaeStorage(FileSystemStorage):
def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL):
super(SaeAndNotSaeStorage, self).__init__(location, base_url)
def get_valid_name(self, name):
try:
if 1:
name = unicodedata.normalize('NFKD', name).encode('ascii', 'ignore')
else:
for k in name:
if self.is_chinese(k):
name = "wszw%s"%random.randint(0,100)
except Exception,e:
name = "%s.jpg"%type(name)
return super(SaeAndNotSaeStorage, self).get_valid_name(name)
@property
def maxsize(self):
return 10*1024*1024
@property
def filetypes(self):
return []
def makename(self,name):
oname = os.path.basename(name)
path = os.path.dirname(name)
if oname.find("_mine_")==0:
oname = oname.replace("_mine_","")
name = os.path.join(path, oname)
return name
try:
fname, hk = oname.split(".")
except Exception,e:
fname, hk = oname, ''
if hk:
rname = "%s_%s.%s"%(random.randint(0,10000), fname,hk)
else:
rname = "%s_%s"%(random.randint(0,10000), fname)
name = os.path.join(path, rname)
#end
return name
def _save(self, name, content):
hz = name.split(".")[-1]
if self.filetypes!='*':
if hz.lower() not in self.filetypes:
raise SuspiciousOperation(u"不支持的文件类型,支持%s"%self.filetypes)
#end
#name = self.makename(name)
if content.size > self.maxsize:
raise SuspiciousOperation(u"文件大小超过限制")
#end
s = sae.storage.Client()
if hasattr(content, '_get_file'):
ob = sae.storage.Object(content._get_file().read())
else:
ob = sae.storage.Object(content.read())
url =s.put('files', name, ob)
return name
def delete(self,name):
s = sae.storage.Client()
try:
s.delete('files', name)
except Exception,e:
pass
class ImageStorage(SaeAndNotSaeStorage):
@property
def maxsize(self):
return 2*1024*1024
@property
def filetypes(self):
return ['jpg','jpeg','png','gif']
class FileStorage(SaeAndNotSaeStorage):
@property
def maxsize(self):
return 10*1024*102
@property
def filetypes(self):
return "*"
#def makename(self, name):
# return name
class ThumbStorage(ImageStorage):
def _save(self, name, content):
image = Image.open(content)
image = image.convert('RGB')
image.thumbnail((50, 50), Image.ANTIALIAS)
output = StringIO.StringIO()
image.save(output,'JPEG')
co = ContentFile(output.getvalue())
output.close()
#end
return super(ThumbStorage, self)._save(name, co)
(4)Model里面加上:
photo = models.ImageField(upload_to='./photos/', max_length = 250, storage = ThumbStorage(), null=True, blank=True)
这里的photos会在storage的Domain里新建文件夹