`
裴小星
  • 浏览: 265781 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
8ccf5db2-0d60-335f-a337-3c30d2feabdb
Java NIO翻译
浏览量:27848
F3e939f0-dc16-3d6e-8c0b-3315c810fb91
PureJS开发过程详解
浏览量:74355
07a6d496-dc19-3c71-92cf-92edb5203cef
MongoDB Java ...
浏览量:63070
社区版块
存档分类
最新评论

Pure JS (3.1):上传下载(利用 HTML5 与 Flash)

阅读更多
Pure JS (3.1):上传下载(利用 HTML5 与 Flash)

  本文主要探讨 JavaScript 文件上传与下载,包括 客户端JS 和 服务器端JS 。
  客户端支持 HTML5,Flash 和传统(隐藏)表单上传。
  服务器端兼容 HTML5 Streaming 方式上传和 Multipart 方式上传,上传与下载都利用了 JAVA 7 NIO 中的 Files.copy(...) 函数。

  其实上传与下载本身并不难,麻烦的是一些细节,比如客户端检查文件大小(怎么绕过浏览器的安全限制?),以及下载文件时中文文件名的乱码问题等。

运行效果

  三种上传方式外观相似,如下图所示:


  直接在前两篇文章中使用的 index.html 中增加了上传按钮。点击上传按钮弹出文件选择框(HTML 或 Flash 方式支持文件多选),选择完成后立即开始上传。上传过程中显示上传进度,期间可以取消;完成后添加到下方的完成列表中,可以移除已经上传完成的文件。
  HTML5 和 表单上传的样式通过 CSS 样式进行设置,Flash 按钮需要加载一张图片(如附件中的 pure.button.png),可以在创建组件的参数中设置样式。

  同时,对于支持 HTML5 的浏览器,还支持拖拽文件进行上传。
  拖拽效果如下:



  只有支持 HTML5 方式的浏览器才提供拖拽功能,如较新版本的 Chrome,FireFox 等;
  Safari 上的拖拽区域不会显示出来(因为没法 drop 到一个 div 上,谁有解决的办法吗?),需要拖拽到上传按钮上,并且同时拖拽多个文件到上传按钮时,也只上传一个文件(这是 Safari 的一个 Bug,有办法解决吗?)。

  点击文件名称进行下载:



  这里比较麻烦的是中文文件名的编码,不同浏览器需要使用不同的编码,在 Java 中进行文件名编码,实现如下:
	private static String encodeFileName(HttpServletRequest req, String name)
			throws UnsupportedEncodingException {
		String agent = req.getHeader("USER-AGENT").toLowerCase();

		if (agent != null
				&& agent.indexOf("firefox") < 0
				&& agent.indexOf("safari") < 0) {
			return URLEncoder.encode(name, "UTF8");
		}

		return new String(name.getBytes("UTF-8"), "ISO8859-1");
	}

  在多数浏览器中使用 UTF8 ,而在 firefox 和 safari 中使用 ISO8859-1 。经测试在 IE、Firefox、Chorme、Safari、Opera 上都能正常显示中文文件名(不过都只测试了较新的浏览器,有其他问题的话请告知,谢谢)。

引用
  关于测试文件大小

  这里的大小限制为 1 GB,这是因为本地测试,使用 HTML5 方式上传时,传输速度很快,200 MB 左右的文件才能看到进度条的效果。
  不过测试 Flash 方式上传是只要选择 10 MB 左右 的文件就可以了,因为速度慢得多,CPU占用率也很高。
  生产环境中,一般将文件大小设置为 10 MB 左右。
  文件大小限制可以在 app.js 中修改。

客户端

  根据客户端浏览器的支持情况,优先选择 HTML5 方式上传,其次是 Flash 上传;
  对于两者都不支持的浏览器,只能使用隐藏的 iframe 和 form 进行上传了。

  优缺点比较如下:
  HTML5: 支持拖拽,多选,客户端检查文件大小,显示上传进度,传输速度快;但 IE, Opera 等浏览器不支持。
  FLash:支持多选,客户端检查文件大小,显示上传进度; 但数据传输格式为 multipart/form-data,传输速度较慢。
  传统:   不支持客户端检查文件大小,不显示上传进度等,传输速度也慢。但所有浏览器均支持。

  文件上传的实现包含两个部分: JavaScript 部分和 ActionScript 部分,代码量都不大。
  JavaScript 部分的主要代码位于 pure.upload.js,它依赖于 jquery.js (1.6 版本)和 pure.js 。
  ActionScript 部分是一个 FlashDevelop 项目,源代码位于 PureUpload.as 。

  pure.upload 组件的使用方式(位于 app.js ):

	var $uploader = $('#file-uploader');

	pure.upload({
		element: $uploader[0],
		action: 'api',
		params: { action: 'upload' },
		sizeLimit: 1000 * 1024 * 1024,
		onComplete: function(file, data){
			// Do more after upload complete ... 
		}
	});

  除此之外还有更多的配置项,下一篇文章里我们再详细探讨。

引用
  相关参考

  客户端 JS 和 AS 的实现参考了以下开源项目的源码:
  AjaxUpload:http://valums.com/ajax-upload
  SWFUpload: http://swfupload.org
  SWFObject: http://code.google.com/p/swfobject

  Flash 开发工具:
  FlashDevelop:http://www.flashdevelop.org


服务器端

  文件上传

  【HTML5 Streaming 类型的格式】
  HTML5 方式上传支持直接将文件内容放在请求的 body 中, 这实际上方便了服务器端的解析。只需要直接通过 Request.getInputStream() 获取输入流就可以了。

  【Muilpart Form Data 类型的数据格式】
  需要增加一个 Filter,对 Jetty 的 MultiPartFilter 做了一些修改,主要是当文件大小超过限制时不创建临时文件,以及解析文件名时不去除 "/"以免后续解析出错。

  Tools 类的 upload 方法提供了供 JS 调用的上传功能的实现,利用了 JAVA 7 NIO 的 Files.copy(...),直接将输入流复制到本地文件。文件上传的 Java部分实现如下:
	public static long upload(HttpServletRequest req, String name, String target)
			throws IOException {
		File dest = new File(target);

		if (isMultiPart(req)) {
			File source = (File) req.getAttribute(name);
			Files.copy(source.toPath(), dest.toPath(), REPLACE_EXISTING);
		} else {
			InputStream is = req.getInputStream();
			Files.copy(is, dest.toPath(), REPLACE_EXISTING);
		}

		return dest.length();
	}

  文件下载

  使用 Files.copy(..),直接将本地文件复制到输出流。Java部分实现如下:
	public static void download(HttpServletRequest req,
			HttpServletResponse res, String name, String source)
			throws IOException {
		String encoded = encodeFileName(req, name);
		String disposition = "attachment; filename=\"" + encoded + '"';

		res.setContentType("application/octet-stream; charset=UTF-8");
		res.setHeader("Content-Disposition", disposition);

		File src = new File(source);
		OutputStream os = res.getOutputStream();
		Files.copy(src.toPath(), os);
	}


  JS 代码

  在服务器端 JS 中,使用importPackage 导入 pure.tools 包,在需要的地方调用 Tools 类的方法进行上传下载。
  api.js 中的相关实现如下:
importPackage(Packages.purejs.tools);

api = {
	// Other codes...

	upload: function(params, req, res) {
		var size = parseFloat(req.getHeader('Content-Length'));

		if (!size || size <= 0 ) {
			throw 'Invalid Content-Length';
		} else if (size > 1000 * 1024 * 1024) {
			throw 'File too large.';
		}

		var prefix = new Date().getTime() + '-';
		var name = prefix + Tools.getFileName(req, 'Filedata');
		var target = 'upload/' + name;
		var size = Tools.upload(req, 'Filedata', target);

		return { name: name, size: size };
	},
	download: function(params, req, res) {
		var name = '' + params.name;
		name = name.substr(name.indexOf('-') + 1);
		var source = 'upload/' + params.name;
		Tools.download(req, res, name, source);
	}
};


  这篇文章就先介绍到这里,下一篇文章里我们再深入探讨其中的实现细节。
  欢迎指出 bug 或提出代码重构等方面的建议。
  谢谢。
5
3
分享到:
评论

相关推荐

    Pure JS (3.2): 上传下载 (HTML5 与 Flash 上传实现,配置项说明)

    标题 "Pure JS (3.2): 上传下载" 涉及到的是使用纯JavaScript技术来处理文件的上传和下载功能,这是Web开发中的重要一环,特别是随着HTML5新特性的引入,使得在浏览器端处理文件变得更加方便。这篇博文可能详细介绍...

    Pure JS (4.3): pure.db.js 的实现(基于 MongoDB Rhino Driver)

    总之,"pure.db.js"的出现为JavaScript开发者提供了一种新的与MongoDB交互的方式,让JavaScript也能直接参与到数据库操作中,拓宽了JavaScript的应用领域,尤其对于熟悉JavaScript而不愿或不能使用其他后端语言的...

    Pure JS (7):小结

    标题中的“Pure JS (7):小结”表明这是一篇关于JavaScript编程的系列教程的第七部分,重点在于总结前面几部分所讲解的核心概念和技巧。JavaScript,也称为JS,是一种广泛用于网页和网络应用的脚本语言,尤其在前端...

    html5文件上传插件Pure HTML5 file upload

    HTML5文件上传插件是利用HTML5的新特性来实现文件上传功能的一种技术手段。相比于传统的文件上传方式,HTML5文件上传提供了更为灵活、强大的特性,包括大文件分块上传、预览、进度条显示等。在本文中,我们将深入...

    PureJS (6.5):配置文件

    标题中的“PureJS (6.5):配置文件”指的是一个关于JavaScript的教程或讨论,特别是聚焦在如何配置JavaScript项目中的文件。PureJS可能是一个强调使用原生JavaScript代码的库或者框架,而不是依赖其他库如jQuery。...

    Pure JS (6.2):结合 Rhino 和 Junit GUI 测试 JS

    标题 "Pure JS (6.2):结合 Rhino 和 Junit GUI 测试 JS" 提到的是一个关于使用纯JavaScript(Pure JS)与Rhino JavaScript引擎以及JUnit进行图形用户界面(GUI)测试的实践方法。Rhino是Mozilla基金会开发的一个...

    purejs:用于构造函数、mixin 和类型测试的纯 JavaScript API

    Pure.js 坚持 JavaScript 的原型性质,没有引入新的想法,允许与内置构造函数更好地集成。安装 npm install purejs或者使用凉亭 bower install purejs鲍尔要使用该组件,您必须使用类的工具捆绑该组件。 例如: ./...

    Pure JS (5.1):在服务器端使用 JQuery DOM 和 JQuery Template

    标题 "Pure JS (5.1):在服务器端使用 JQuery DOM 和 JQuery Template" 暗示了这篇博客可能探讨如何在非浏览器环境,比如服务器端,利用JavaScript的JQuery库来处理DOM操作和模板渲染。虽然JQuery通常与前端开发关联...

    PureJS (6.6):配置 Spket 智能感知

    本篇将详细介绍如何配置Spket以实现对PureJS(一种轻量级的JavaScript库)的智能支持。 首先,我们需要下载并安装Spket IDE。访问其官方网站或者通过GitHub等渠道获取最新版本。安装完成后,打开Spket IDE并创建一...

    Pure JS (1): 在 jetty 上运行 JavaScript

    标题 "Pure JS (1): 在 jetty 上运行 JavaScript" 暗示了本文将探讨如何在 Jetty 服务器上执行纯 JavaScript 代码。Jetty 是一个轻量级、开源的 Java Web 应用服务器,而 Pure JS 提示我们将讨论如何在后端环境中...

    PureJS (6.4):利用 proxy 对象实现权限控制和数据校验

    在JavaScript的世界里,Proxy对象是一个强大的工具,它允许我们创建代理来拦截并定制对原对象的访问行为。在本文中,我们将深入探讨如何利用Proxy对象实现权限控制和数据校验,这在构建复杂的前端应用或者提供更加...

    todo-list-pure-js::check_mark_button:(已完成)

    【标题】"todo-list-pure-js::check_mark_button:(已完成)" 指的是一款使用纯JavaScript实现的待办事项列表应用。这个项目完全不依赖任何外部库或框架,仅使用JavaScript的核心功能来创建交互式的用户界面。在...

    Pure (6.7):部署

    标题 "Pure (6.7):部署" 暗示我们即将探讨的是关于Pure JavaScript库的一个特定版本(6.7)的部署策略。Pure是一个轻量级、模块化的JavaScript库,它专注于提供实用的UI组件和功能,尤其适用于前端开发。在6.7版本...

    Pure JS (5.2):服务器端与客户端共用页面渲染代码

    《Pure JS (5.2):服务器端与客户端共用页面渲染代码》 在现代Web开发中,为了提高用户体验和加载速度,服务器端渲染(Server-Side Rendering, SSR)和客户端渲染(Client-Side Rendering, CSR)是两种常见的技术...

    Pure JS (2): 热部署 (利用 JDK 7 NIO 监控文件变化)

    标题 "Pure JS (2): 热部署 (利用 JDK 7 NIO 监控文件变化)" 提到了一个关于JavaScript开发的话题,特别是热部署(Hot Deployment)的概念,这是一种在开发过程中无需重启应用就能自动更新代码的技术。...

    pure-website:仅基础(HTML-CSS-JS)

    "pure-website:仅基础(HTML-CSS-JS)"是一个项目,专注于使用最核心的Web技术——HTML、CSS和JavaScript来构建网站。这个项目很可能是一个简洁、高效的网页设计框架,旨在提供一个轻量级的解决方案,让开发者可以...

    Pure JS (6.1):使用 Rhino Shell 和 Debugger 运行和调试 JS

    **文件名称列表分析:** "PureJS"可能是博客文章的系列名称,但没有具体的文件内容,我们只能假设这篇文章是该系列的一部分,可能包含了一系列关于使用Rhino Shell和Debugger进行JavaScript开发的实践教程或案例。...

    pure-upload:完全无依赖的纯JS文件上传库

    纯JS(TS)上传库,没有与Google Chrome,Firefox,IE10 +,Edge和现代移动浏览器兼容的依赖项。 安装 直接从页面下载ZIP文件,并将其包含到您的项目中。 通过npm通过npm install pure-upload --save或yarn add ...

Global site tag (gtag.js) - Google Analytics