SAE-禁止本地IO问题

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里新建文件夹