django:自定义静态文件服务器
2017-10-14 22:33
871 查看
静态文件使用nginx是比较有效率的,但是有时,我们需要对文件下载做细粒度的处理,比如鉴权下载,此时就需要写代码了。
下面将一步步实现一个自定义的文件handler。
要下载一个文件,需要返回正确的 Content-Type 和 Content-Disposition。
get_real_path 是把相对路径转成硬盘的实际路径,自已实现吧
具体看代码:
比如,可以hack真实的文件路径。如果权限不正确,就返回一个error的图片给他。
当我们把实现改成这样,很快,你会发现服务器爆炸了。
一般来说,浏览器请求静态资源会带上一个头 If-Modified-Since,文件服务器会根据这个头,判定文件是否已经修改。如果文件不变,则直接返回code 304给浏览器。浏览器将直接使用缓存。
我们的文件服务器漏了这一步。所以,每次请求,服务端都会把文件读取任劳任怨的重新来一次。这样用户体验很差。尤其是图片用户。
具体参考:http://wiki.jikexueyuan.com/project/django-chinese-docs-1.8/14-1-conditional-content-processing.html
代码可以这么写:
然后,我们给handler加个佐料,注意,装饰的参数要和handler的一样(?存疑)
重新部署,刷新同一页面,304 code 又回来了。
下面将一步步实现一个自定义的文件handler。
关闭自带的static handler
确保没有开启 django.contrib.staticfilesINSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', # 'django.contrib.staticfiles',
定义文件下载handler
读取一个文件建议使用迭代器,否则内存吃不消。要下载一个文件,需要返回正确的 Content-Type 和 Content-Disposition。
get_real_path 是把相对路径转成硬盘的实际路径,自已实现吧
具体看代码:
from django.http import HttpResponse, StreamingHttpResponse .... def handler_statics(request, path): short_file_name, real_file_path = get_real_path(request, path) response = StreamingHttpResponse(readFile(real_file_path)) response['Content-Type'] = get_right_content_type(short_file_name) response['Content-Disposition'] = get_right_content_disposition(short_file_name) logging.info(u"handler_statics type {} path {}".format(get_right_content_type(short_file_name), real_file_path)) return response def get_right_content_disposition(filename): filename = filename.lower() img_types = ['jpg', 'png', 'jpeg', 'gif'] content_disposition = "" for img_type in img_types: if img_type in filename: content_disposition = u'inline;filename="{}"'.format(filename) break if content_disposition == "": content_disposition = u'attachment;filename="{}"'.format(filename) return content_disposition def get_right_content_type(filename): filename = filename.lower() if ".css" in filename: return "text/css" if ".png" in filename: return "image/png" if '.jpg' in filename or '.jpeg' in filename: return "image/jpeg" else: return "application/octet-stream" def readFile(file_name, chunk_size=512): try: with open(file_name, 'rb') as f: while True: c = f.read(chunk_size) if c: yield c else: break except: yield b""
对用户鉴权
既然自己实现了文件服务器,那鉴权还不是小儿科。比如,可以hack真实的文件路径。如果权限不正确,就返回一个error的图片给他。
def get_real_path(request, path): real_file_path = u"{}/dazhu/static/{}".format(os.getcwd(), path) if real_file_path.endswith("/"): real_file_path = real_file_path[:-1] short_file_name = real_file_path.split("/") short_file_name = short_file_name[len(short_file_name)-1] # 对 album 要鉴权 if "album/" in path: real_file_path = handler_album(request, short_file_name, real_file_path) return short_file_name, real_file_path # 相册要鉴权 def handler_album(request, short_name, file_path): pic = Photoes.objects.get(rndName = short_name) if pic.phototype == "private": if not request.user.is_authenticated(): file_path = u"{}/dazhu/static/{}".format(os.getcwd(), u'/images/dazhu.jpg') return file_path
服务器爆炸了?
如果本文就这么完了,那就太对不起观众了。当我们把实现改成这样,很快,你会发现服务器爆炸了。
一般来说,浏览器请求静态资源会带上一个头 If-Modified-Since,文件服务器会根据这个头,判定文件是否已经修改。如果文件不变,则直接返回code 304给浏览器。浏览器将直接使用缓存。
我们的文件服务器漏了这一步。所以,每次请求,服务端都会把文件读取任劳任怨的重新来一次。这样用户体验很差。尤其是图片用户。
实现304
可爱的django给我们提供了一个装饰器 condition。具体参考:http://wiki.jikexueyuan.com/project/django-chinese-docs-1.8/14-1-conditional-content-processing.html
代码可以这么写:
from django.views.decorators.http import last_modified def get_file_m_time(request, path): try: _, real_file_path = get_real_path(request, path) mtime = time.ctime(os.path.getmtime(real_file_path)) logging.info("last modified: {}".format(mtime)) return datetime.datetime.strptime(mtime, "%a %b %d %H:%M:%S %Y") except: return datetime.datetime.now()
然后,我们给handler加个佐料,注意,装饰的参数要和handler的一样(?存疑)
@last_modified(get_file_m_time) def handler_statics(request, path): short_file_name, real_file_path = get_real_path(request, path) ...
重新部署,刷新同一页面,304 code 又回来了。
相关文章推荐
- django 简易博客开发 3 静态文件、from 应用与自定义
- django静态文件服务器的配置
- django项目部署在Apache服务器中,静态文件路径的注意点
- Django开发服务器无法找到静态文件的解决方法
- django 简易博客开发 3 静态文件、from 应用与自定义
- django 简易博客开发 3 静态文件、from 应用与自定义
- 在django中处理和压缩静态文件
- 缓存nginx服务器的静态文件
- django使用静态文件
- Django使用静态文件css ,js,多媒体
- Django使用模板后无法找到静态资源文件
- Django静态文件配置
- django 1.8 官方文档翻译: 6-6-4 部署静态文件
- django中url,静态文件,POST请求的配置
- ASP.NET性能优化 之 构建自定义文件缓存 输出缓存(即静态HTML缓存)
- django - 本地访问不了静态文件的解决方法
- [Django]静态文件:如何在网页中显示图片,css,js等静态文件
- Django调用css、img、js等静态文件
- Django web server: html引用静态文件(css, js)
- springboot1.1.0自定义静态文件配置bug