文章目录

  • 文件上传的服务端技术解析
  • 基于Ajax技术实现的文件上传客户端
    • 方法1:使用 ajaxfileupload.js
    • 方法2:仅依赖 jquery.js
  • 文件下载的服务端技术解析

文件上传的服务端技术解析

常言到,爱有多深、恨有多切。tornado服务器就是这样一个矛盾体,它的缺点和它的优点一样,显著且强烈。有人认为,文件上传是tornado的重大缺陷之一,它把用户上传的文件存放在内存中——这意味着多用户同时上传文件的话,内存的开销会急剧增加。不过我倒是觉得,这反倒让很多事情变得简单了,比如,你想对用户上传的内容做处理的话,不用再打开文件了,因为内容就在内存中。再者说,在tornado的异步机制下,我不确定真的能够多用户同时上传文件。这是一个有趣的问题。

好了,言归正传吧。假定文件上传的表单如下:

<form id="form_upload" action="/demo/upload" enctype="multipart/form-data" method="post"><input type="file" name="want_to_upload_file_1"/><br/><input type="file" name="want_to_upload_file_2"/><br/><input type="submit" value="上传"/>
</form>

机制是允许一次上传多个文件的。这里有几个问题需要特别说明一下。

  • 在提交表单之前,需要为form指定action和method的属性值,如果是上传文件,还要设置enctype=“multipart/form-data”。这三个属性,可以写在html中,也可以在submit之前用js的方法为其赋值

  • 文件浏览是file类型的input标签自备的功能,程序员无法在浏览器框架内操作本地文件。该标签的name属性,是用来区别于其他文件的标识,不是文件名,也不是文件对象,更不是文件内容

上面的表单被提交到/demo/upload(假定上传的第1个文件名为dqd.jpg,第2个文件名为intro.png),这个请求的对象中包含files字典,上传的全部文件的信息都包含在这个结构中。我们来看看这个request.files的真实面貌:

def post(self):print self.request.files.keys() # [u'want_to_upload_file_1', u'want_to_upload_file_2']print type(self.request.files['want_to_upload_file_1']) # list,长度为1meta_file_1 = self.request.files['want_to_upload_file_1'][0]print meta_file_1.keys() # ['body', 'content_type', 'filename']print len(meta_file_1['body']) # 31492,文件长度print meta_file_1['content_type'] # image/jpegprint meta_file_1['filename'] # dqd.jpg

有了这些素材,我们就可以无所不能地应对客户需求了。比如,不做任何处理,仅仅用原文件名保存在指定路径下(假设保存在/static/image/wiki目录下):

PROJECT_PATH = os.path.split(os.path.realpath(__file__))[0]
upload_path = os.path.join(PROJECT_PATH, 'static', 'image', 'wiki')
file_name = os.path.join(upload_path, meta_file_1['filename'])with open(file_name, 'wb') as fp:fp.write(meta_file_1['body'])

很多时候,需要对用户上传的文件重命名(比如,用时间戳为文件名),但文件后缀名不变。

fn, ext = os.path.splitext(meta_file_1['filename'])
fn = '%d%s' % (time.time()*1000, ext)
file_name = os.path.join(upload_path, fn)

如果需要对用户上传的文件类型做检查,请使用文件的content_type,而不是文件的扩展名,因为前者更规范。比如,JPEG类型的图片文件,其后缀名可能是.jpg|.jpeg|.JPG|.JPEG中的一种,而前者只有“image/jpeg”一种表示法。

关于文件的content_type,网上资料多如牛毛,请自行搜索。

处理用户上传的图片文件时,除了限制文件大小,有时候还要做缩放处理,甚至一并生成缩略图,此时就需要将文件内容转成易于处理的图像对象,比如,pil的Image

from PIL import Image
import StringIOpilImg = Image.open(StringIO.StringIO(meta_file_1['body']))
print pilImg.size

至于如何缩放、如何保存为文件,请自行检索相关资料。

基于Ajax技术实现的文件上传客户端

假定上传文件的表单是这样的:

<form id="form_upload" action="/demo/upload" enctype="multipart/form-data" method="post"><input type="file" name="wiki_img" id="wiki_img" /><br /><input id="doUpload" type="button" value="上传" />
</form>

方法1:使用 ajaxfileupload.js

<script src="jquery.js"></script>
<script src="ajaxfileupload.js"></script>
<script type="text/javascript">$("#doUpload").click(function(){$.ajaxFileUpload({url:'/demo/upload',secureuri:false,fileElementId:'wiki_img',dataType: 'json',success: function(data){alert(data);}});});
</script>

方法2:仅依赖 jquery.js

<script src="jquery.js"></script>
<script type="text/javascript">var formData = new FormData();formData.append("file", $("#wiki_img")[0].files[0]);formData.append("filename", $("#wiki_img").val());$.ajax({url : '/demo/upload',type : 'POST',async : false,data : formData,processData : false,contentType : false,beforeSend:function(){$("#upload_tips").html("正在进行,请稍候");},success : function(data) {alert(data);}});
</script>

文件下载的服务端技术解析

相对于上传,文件的下载就简单得多。只需要记住两点:开始前告诉浏览器要传输的文件类型,结束前对浏览器说拜拜。文件类型并不是固定的,需要根据文件的实际情况来选择。详情请自行检索。

def get(self):self.set_header ('Content-Type', 'application/octet-stream')with open(filename, 'rb') as f:while True:data = f.read(buf_size)if not data:breakself.write(data)self.finish()

配合seek命令,可以实现更复杂的下载请求,比如,断点续传、分块下载、ajax异步请求等。

基于tornado服务器的文件上传和下载相关推荐

  1. java使用Jsch实现远程操作linux服务器进行文件上传、下载,删除和显示目录信息...

    1.java使用Jsch实现远程操作linux服务器进行文件上传.下载,删除和显示目录信息. 参考链接:https://www.cnblogs.com/longyg/archive/2012/06/2 ...

  2. 在windows环境下ftp服务器的文件上传和下载

    在windows环境下ftp服务器的文件上传和下载 mo 一.上传本地文件 第一步:登录FTP服务器.在开始菜单中输入cmd,回车进入.输入ftp进入服务器,输入命令格式:open FTP服务器地址 ...

  3. Mr.张小白(案例:基于Spring MVC实现文件上传和下载)

    基于Spring MVC实现文件上传和下载 一.步骤 1.引入相关依赖pom.xml <?xml version="1.0" encoding="UTF-8&quo ...

  4. 基于FTP协议实现文件上传与下载

    目录 一.FTP简介 二.关于FTP服务器 三.文件上传 分步讲解: 完整实现代码: 四.下载文件 分步讲解: 完整实现代码: 小结 一.FTP简介 FTP(File Transfer Protoco ...

  5. Java基于nfs-client包实现NFS协议连接linux服务器进行文件上传与下载操作源码

    添加依赖 // https://mvnrepository.com/artifact/com.emc.ecs/nfs-clientcompile group: 'com.emc.ecs', name: ...

  6. 基于TCP协议的文件上传与下载

    一.前言 TCP协议:传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793 定义.传输控制 ...

  7. 科普|不同协议下远程服务器文件上传_下载优劣对比

    作为一个程序员,如果不知道如何进行远程服务器的文件上传与下载,实在是一件尴尬的事情.打开百度,搜索「远程服务器 上传下载」,你能得到 63,100,000 个搜搜结果,五花八门的操作方式的让人眼花缭乱 ...

  8. linux服务器批量文件上传,Windows定时任务下载linux服务器批量文件到本地

    编写批文件 1.1 编写main.bat文件 E: cd logs ftp -n -s:"E:\logs\mget.bat" 1.2 编写mget.bat文件 open ip地址 ...

  9. java spring文件下载_SpringMVC实现文件上传和下载的工具类

    本文主要目的是记录自己基于SpringMVC实现的文件上传和下载的工具类的编写,代码经过测试可以直接运行在以后的项目中. 开发的主要思路是对上传和下载文件进行抽象,把上传和下载的核心功能抽取出来分装成 ...

最新文章

  1. 导入语句 python_Python导入语句说明
  2. Matlab与机器学习 -- BP网络神经元上的转移函数
  3. 索尼AI CEO:我们要让AI在30年内拿到诺贝尔奖
  4. Nginx —— 检查配置文件nginx.conf的正确性命令(-t)
  5. 物联网协议之CoAP协议开发学习笔记之术语解释
  6. Linux(fedora 10)Hello World模块
  7. React开发(151):外部引入记得导出
  8. 闭环检测python_hdl_graph_slam源码解读(七):闭环检测
  9. JUnit测试框架使用介绍
  10. 微信公众号小程序怎么做 微信公众号小程序制作教程
  11. 计算机组装专周实训心得,电脑组装实训心得3篇
  12. 域名Whois查询API,域名Whois,域名历史Whois
  13. Lenovo联想G460无电池ThinkPad强制刷新BIOS的方法,非电池补丁
  14. ASP.NET Core Razor 布局视图 - ASP.NET Core 基础教程 - 简单教程,简单编程
  15. 学信网学位认证报告在哪
  16. AD账号密码过期邮件提醒-powershell实现--密码加密(新增)
  17. Learning Saliency Propagation for Semi-Supervised Instance Segmentation
  18. 大三保研夏令营须知及前期准备工作
  19. 达人评测 iPad mini6怎么样 mini6参数配置
  20. ERROR org.hibernate.internal.SessionImpl - HHH000346: Error during managed flush [Batch update retur

热门文章

  1. Uber Go 风格指南中文版
  2. Echarts中太阳图(Sunburst)的实例
  3. 在 Visual Studio Code 中添加自定义的代码片段
  4. 无孔不入的Android侵入Windows系统
  5. app常见性能测试点
  6. 基于51单片机的传送带产品计数器
  7. 程序猿从不缺对象,想要随时可以new出来一个
  8. Redis源码学习(20),学习感悟
  9. 程序员在工作中这样做,会省去一大堆烦恼
  10. 非班课Python习题