上一篇博客记录了如何将model中的图片存入FTP,通过一个第三方的storages简单的实现了,但是后续我发现如果想在浏览器通过url直接获取图片,就不太容易了(大神轻喷,小弟自学django和python,基础知识差),于是我从头开始学习,当浏览器输入一段URL的时候,django后台究竟做了什么

一.URL处理

django在处理我们自己设计的业务请求的时候都会通过urls.py这里面的url()方法处理

def url(regex, view, kwargs=None, name=None):
if isinstance(view, (list, tuple)):
# For include(...) processing.
urlconf_module, app_name, namespace = view
return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
elif callable(view):
return RegexURLPattern(regex, view, kwargs, name)
else:
raise TypeError('view must be a callable or a list/tuple in the case of include().')

简单的使用过url()或者看url的源码都知道,这里的第一个参数是获取端口号后面的url字符,用来做正则匹配的,第二个参数是处理这个请求的view方法,由于我想请求的是一个图片,只是一个静态文件,所以我联想到django在处理静态文件的url的时候,应该也会有一个特殊的方法去处理,而且这个方法是依赖setting中的debug模式是否开启(这也就是为什么关了debug,部署到服务器上的时候,django自身是提供不了静态文件的访问,因为web服务器更适合做这些工作),但是在这里卡住了。。。不知道要怎么去找这个方法,查了好久资料也没有找到,后来我想起了django的media应该和静态文件是一样的

(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.STATIC_PATH}),

这个media是一般处理用户上传的文件之类的,于是我找到了django.views.static.serve方法

def serve(request, path, document_root=None, show_indexes=False):
......
content_type, encoding = mimetypes.guess_type(fullpath)
content_type = content_type or 'application/octet-stream'
response = FileResponse(open(fullpath, 'rb'), content_type=content_type)
response["Last-Modified"] = http_date(statobj.st_mtime)
if stat.S_ISREG(statobj.st_mode):
response["Content-Length"] = statobj.st_size
if encoding:
response["Content-Encoding"] = encoding
return response

这个方法前面我省略了,大概就是判断一下URL指向的是否是一个文件,如果不是就返回报错了,真正处理的是这部分,它是返回了一个FileResponse的一个类型,看名字可以发现应该是直接返回一个文件,其实在这里我踩了好多坑,一直不知道如何给浏览器直接返回一个文件,甚至都已经把二进制文件获取到了,但是直接返回给浏览器就是乱码。。。。,不知道是不是根本原因,前端知识有限,这个FileResponse会附带一个content_type,这是一个http返回的header,将类型指定为图片,就可以展示出来了,至于这个类型,看源码也可以看到,前面用了一个mimetypes.guess_type()的方法,我大致了解了一下,这个方法只需要传URL给它就可以了,它会根据这个 URL的后缀判断,不会真的去把这个文件拿到再判断,所以不用担心它会再一次去ftp里取文件。此外,还有一些其他的header也可以设置,但是这里只用到type应该就可以了,其他的header看自己的需求

参考到这里,我们可以知道,大致思路就是自己需要重写一个url里media的view方法,用这个方法取到图片,然后返回给前端就可以了

一.get_from_ftp

这里我重写一个get_from_ftp方法来实现,其实这里我走了许多弯路。。。不知道要怎么通过storage获取到文件,而且也不知道对应的参数是什么,我这里查阅了大量的资料,然后一路碰壁,各种看源码,各种猜测,打断点。。。中间的经历过于痛苦,就不细说了(主要原因还是自己没有经验,这次也算学习到了思路),主要就是看其他地方是如何使用storage的,然后我使用的是第三方重写的ftpstorage,和其他的storage一样,是通过open方法来获取文件,参数就是路径+文件名,其实这里可以直接用media的url传过来的参数  '^media/(?P<path>.*)$'

url.py

url(r'^media/(?P<path>.*)$', get_from_ftp),

get_from_ftp

def get_from_ftp(request,path):
storage=FTPStorage()
file=storage.open(path)
content_type, encoding=mimetypes.guess_type(path)
return FileResponse(file, content_type=content_type)

 

其实很简单的一个逻辑,只要知道storage如何使用,很轻松就可以完成这一过程,主要还是要养成好的思考习惯,多看源码,多看文档

实现model中的文件上传FTP(二)的更多相关文章

  1. 实现model中的文件上传FTP(一)

    由于在django的model中配置了filefield或者imagefield配置了upload_to参数只能将用户上传的文件上传到项目本地,就算重定向到项目外也只是直接读取文件系统,这样对未来的项 ...

  2. Java中的文件上传和下载

    文件上传原理: 早期的文件上传机制: 在TCP/IP中.最早出现的文件上传机制是FTP.他是将文件由客户端发送到服务器的标准机制. jsp中的文件上传机制: 在jsp编程中不能使用FTP的方法来上传文 ...

  3. IIS 7 中设置文件上传大小的方法

    在IIS 6.0中设置文件上传大小的方法,就是配置如下节点: <system.web> <httpRuntime maxRequestLength="1918200&quo ...

  4. 在WebBrowser中通过模拟键盘鼠标操控网页中的文件上传控件(转)

    引言 这两天沉迷了Google SketchUp,刚刚玩够,一时兴起,研究了一下WebBrowser. 我在<WebBrowser控件使用技巧分享>一文中曾谈到过“我现在可以通过WebBr ...

  5. PHP中,文件上传实例

    PHP中,文件上传一般是通过move_uploaded_file()来实现的.  bool move_uploaded_file ( string filename, string destinati ...

  6. MVC中的文件上传-小结

    web开发中,文件的上传是非常基本功能之一. 在asp.net中,通常做法是利用webservice 来接收文件请求,这样做的好处就是全站有了一个统一的文件上传接口,并且根据网站的实际情况,可以将we ...

  7. ASP.NET中的文件上传大小限制的问题

    一.文件大小限制的问题 首先我们来说一下如何解决ASP.NET中的文件上传大小限制的问题,我们知道在默认情况下ASP.NET的文件上传大小限制为2M,一般情况下,我们可以采用更改WEB.Config文 ...

  8. struts2中的文件上传,文件下载

    文件上传: Servlet中的文件上传回顾 前台页面 1.提交方式post 2.表单类型 multipart/form-data 3.input type=file 表单输入项 后台 apache提交 ...

  9. 转:在Struts 2中实现文件上传

    (本文转自:http://www.blogjava.net/max/archive/2007/03/21/105124.html) 前一阵子有些朋友在电子邮件中问关于Struts 2实现文件上传的问题 ...

随机推荐

  1. Scala类型系统——高级类类型(higher-kinded types)

    高级类类型就是使用其他类型构造成为一个新的类型,因此也称为 类型构造器(type constructors).它的语法和高阶函数(higher-order functions)相似,高阶函数就是将其它 ...

  2. C# 检测字符串是否为数字

    long n; 1. ], ].All(char.IsDigit); //识别空字符时候 会认为是数字 string str0 = ""; string str1 = " ...

  3. 理解Python中编码的应用

    完全理解字符编码 与 Python 的渊源前,我们有必要把一些基础概念弄清楚,虽然有些概念我们每天都在接触甚至在使用它,但并不一定真正理解它.比如:字节.字符.字符集.字符码.字符编码. 字节 字节( ...

  4. Jenkins构建项目

    创建项目 Jenkins版本:Jenkins ver.2.150.1 在Jenkins首页点击‘New 任务’进入创建任务页面,在‘Enter an item name’输入框内输入项目名称,选择Je ...

  5. Object.assign和序列/反序列

    Object.assign let testObj = { a:[1,2,4], b:{ name:'ls', school:['huf','yelu'], parent:{ father:'lili ...

  6. 使用JAVA写一个简单的日历

    JAVA写一个简单的日历import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateF ...

  7. BZOJ : [Usaco2013 Nov]Crowded 单调队列

    正反两遍个来一次单调队列 DP 即可. Code: #include<cstdio> #include<deque> #include<algorithm> usi ...

  8. Office 2013 提示找不到 Office.zh-cn\XXXXX

    1.先卸载Office 2013(已经卸载了的无视这一步)2.卸载Office 2013 后把C:\ProgramData\Microsoft\OFFICE文件删掉.3.删除下列注册信息1).依次点击 ...

  9. 文件操作(day15)

    调用函数可以使用被调用函数动态分配的 存储区 calloc函数也可以动态分配一组连续的 存储区 这个函数可以把所有动态分配的存储区 内容设置成0 为了使用这个函数也需要包含stdlib.h头文件 这个 ...

  10. 继续聊WPF——如何获取ListView中选中的项

    在WPF中获Listview中选中的项,与WinForm里面有着很大的区别,要亲身去研究一下在WPF中如果处理,其实也不难,来,下面我们一起来通过一个简单的示例来感悟一下吧. 第一步就是建立一个WPF ...