处理AJAX表单###

用Express处理AJAX表单非常简单;甚至可以使用相同的处理程序来处理AJAX请求和常规的浏览器回退。

  • HTML文件 (/views/newsletter.handlebars)
<div class="formContainer">
<form class="form-horizontal newsletterForm" role="form"
action="/process?form=newsletter" method="POST">
<input type="hidden" name="_csrf" value="{{csrf}}">
<div class="form-group">
<label for="fieldName" class="col-sm-2 control-label">Name</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="fieldName" name="name">
</div>
</div>
<div class="form-group">
<label for="fieldEmail" class="col-sm-2 control-label">Email</label>
<div class="col-sm-4">
<input type="email" class="form-control" required id="fieldName" name="email">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button type="submit" class="btn btn-default">Register</button>
</div>
</div>
</form>
</div>
{{#section 'jquery'}}
<script>
$(document).ready(function(){
$('.newsletterForm').on('submit', function(evt){
evt.preventDefault();
var action = $(this).attr('action');
var $container = $(this).closest('.formContainer');
$.ajax({
url: action,
type: 'POST',
success: function(data){
if(data.success){
$container.html('<h2>Thank you!</h2>');
} else {
$container.html('There was a problem.');
}
},
error: function(){
$container.html('There was a problem.');
}
});
});
});
</script>
{{/section}}
  • 应用程序文件
app.post('/process', function(req, res){
if(req.xhr || req.accepts('json,html')==='json'){
// 如果发生错误,应该发送 { error: 'error description' }
res.send({ success: true });
} else {
// 如果发生错误,应该重定向到错误页面
res.redirect(303, '/thank-you');
}
});

Express提供了两个方便的属性:req.xhrreq.accepts。如果是AJAX请求(XHR是XML HTTP请求的简称,AJAX依赖于XHR),req.xhr值为truereq.accepts试图确定返回的最合适的响应类型。在此例中,req.accepts('json,html')询问最佳返回格式是JSON还是HTML:这可以根据Accepts HTTP头信息推断出来,它是浏览器提供的可读的、有序的响应类型列表。如果是一个AJAX请求,或者User-Agent明确要求JSON优先于HTML,那么就会返回合适的JSON数据;否则,返回一个重定向。

在这个函数里可以做任何处理:通常会将数据保存到数据库。如果出现问题,则返回一个err属性(而不是success)的JSON对象,或者重定向到一个错误页面(如果不是AJAX请求)。

在此例中,假设所有AJAX请求的是JSON数据,但是并没有要求AJAX通信必须使用JSON(事实上,“X”在AJAX中代表XML)。这个方法是jQuery友好的,因为通常jQuery假定所有数据都是JSON格式的。如果想让AJAX处理程序通用,或者知道AJAX请求使用JSON之外的东西,你应该根据Accepts头信息(可以根据req.accepts辅助方法轻松访问)返回一个适当的响应。如果响应完全基于Accepts头信息,你或许想看看c,这是一个可以根据客户端预期轻松做出适当响应的简便方法。如果这样做,必须保证用jQuery发起AJAX请求时设置dataTypeaccepts属性。

文件上传###

一般,文件上传可以使用Connect的内置中间件multipart来处理。但是,这个中间件已经从Connect中移除了,一旦Express更新了对Connect的依赖项,它也将从Express中消失,所以我强烈建议你不要使用这个中间件。

对于复合表单处理,目前有两种流行而健壮的选择:BusboyFormidable。Formidable要稍微简单一些,因为它有一个方便的回调方法,能够提供包含字段和文件信息的对象。对于Busboy而言,必须对每一个字段和文件事件进行监听。

  • (views/contest/vacation-photo.handlebars)
<form class="form-horizontal" role="form"
enctype="multipart/form-data" method="POST"
action="/contest/vacation-photo/{year}/{month}">
<div class="form-group">
<label for="fieldName" class="col-sm-2 control-label">Name</label>
<div class="col-sm-4">
<input type="text" class="form-control"
id="fieldName" name="name">
</div>
</div>
<div class="form-group">
<label for="fieldEmail" class="col-sm-2 control-label">Email</label>
<div class="col-sm-4">
<input type="email" class="form-control" required
id="fieldName" name="email">
</div>
</div>
<div class="form-group">
<label for="fieldPhoto" class="col-sm-2 control-label">Vacation photo
</label>
<div class="col-sm-4">
<input type="file" class="form-control" required accept="image/*" id="fieldPhoto" name="photo">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>

注意,我们必须指定enctype="multipart/form-data"来启用文件上传。我们也可以通过accept属性来限制上传文件的类型(这是可选的)。

  • 安装Formidable(npm install --save formidable)并创建一下路由处理程序:
var formidable = require('formidable');

app.get('/contest/vacation-photo',function(req,res){
var now = new Date();
res.render('contest/vacation-photo',{
year: now.getFullYear(),month: now.getMont()
});
}); app.post('/contest/vacation-photo/:year/:month', function(req, res){
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files){
if(err) return res.redirect(303, '/error');
console.log('received fields:');
console.log(fields);
console.log('received files:');
console.log(files);
res.redirect(303, '/thank-you');
});
});

(year和month被指定为路由参数)。继续运行,检查控制台日志。你会发现表单字段如你预期的那样:是一个有字段名称属性的对象。文件对象包含更多的数据,但这是相对简单的。对于每一个上传的文件,你会看到属性有文件大小、上传路径(通常是在临时目录中的一个随机名字),还有用户上传此文件的原始名字(文件名,而不是整个路径,出于安全隐私考虑)。

接下来如何处理这个文件就取决于你了:可以将它保存到数据库,将其复制到更持久的位置,或者上传到云端文件存储系统。记住,如果你基于本地存储保存文件,应用程序不能很好地扩展,基于云端存储是一个更好的选择。

jQuery文件上传###

如果想为用户提供真正别出心裁的文件上传,可拖拽,可以看到上传文件缩略图,并查看进度条,那推荐 Sebastian Tschan的jQuery File Upload

要显示文件缩略图,jquery-file-upload-middleware使用[ImageMagick](http://www.imagemagick.org

在Ubuntu和Debian系统中,可以使用apt-get install imagemagick安装ImageMagick;在OS X中,你可以使用brew install imagemagick来安装。对于其他操作系统,请参考[ImageMagick文档](http://www.imagemagick.org/script/binary-releases.php)。

  • 首先,安装jquery-file-upload-middleware包(npm install --save jquery-file-upload-middleware),然后在你的应用文件中添加以下代码:
var jqupload = require('jquery-file-upload-middleware');

app.use('/upload', function(req, res, next){
var now = Date.now();
jqupload.fileHandler({
uploadDir: function(){
return __dirname + '/public/uploads/' + now;
},
uploadUrl: function(){
return '/uploads/' + now;
},
})(req, res, next);
});

除非为所有访问者提供一个共用的文件上传区域,否则可能要将上传文件区分开来。简单的方法是创建一个时间戳目录来存储文件。更实际的做法是使用用户ID或其他唯一ID来创建子目录。

请注意,我们将jQuery File Upload中间件挂载在/upload前缀上。你可以在这里使用任何前缀,但是确保该前缀不用于其他路由或中间件,不然会干扰文件上传操作。

  • 接下来是文件上传的视图,你可以直接复制演示上传代码:你可以在project's GitHub页面上传最新项目包。

如果你只想要一个可构建的最小示例,需要如下脚本:

js/vendor/jquery.ui.widget.jsjs/jquery.iframe-transport.js和js/jquery.fileupload.js。

在这个最小实现中,我们将<input type="file">元素放在<span>中,还有一个<div>用来列出所有已上传文件:

<span class="btn btn-default btn-file">
Upload
<input type="file" class="form-control" required accept="image/*"
id="fieldPhoto" data-url="/upload" multiple name="photo">
</span>
<div id="uploads"></div>
  • 然后我们加上jQuery File Upload:
{{#section 'jquery'}}
<script src="/vendor/jqfu/js/vendor/jquery.ui.widget.js"></script>
<script src="/vendor/jqfu/js/jquery.iframe-transport.js"></script>
<script src="/vendor/jqfu/js/jquery.fileupload.js"></script>
<script>
$(document).ready(function(){ $('#fieldPhoto').fileupload({
dataType: 'json',
done: function(e, data){
$.each(data.result.files, function(index, file){
$('#fileUploads').append($('<div class="upload">' +
'<span class="glyphicon glyphicon-ok"></span>' +
'&nbsp;' + file.originalName + '</div>'));
});
}
});
});
</script>
{{/section}}
  • 为上传按钮添加CSS动态样式:
.btn-file {
position: relative;
overflow: hidden;
}
.btn-file input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
font-size: 999px;
text-align: right;
filter: alpha(opacity=0);
opacity: 0;
outline: none;
background: white;
cursor: inherit;
display: block;
}

注意,<input>标签里的data-url属性必须和用于中间件的路由前缀相匹配。在这个简单示例中,当一个文件上传完成后,一个<div class="upload">元素会附加到之前的<div id="uploads">下面。这个列表只显示文件名和大小,不提供删除、运行或者缩略图功能。但这是一个好的开始。定制jQuery File Upload演示程序会让人望而生畏,如果你的视角完全不同,从最小程序开始逐渐向上构建,而不是从演示和定制开始,可能会更简单。不管怎样,你会在jQuery File Upload文档网页找到你想要的资源。

express-11 表单处理(2)的更多相关文章

  1. ddms(基于 Express 的表单管理系统)源码学习

    ddms是基于express的一个表单管理系统,今天抽时间看了下它的代码,其实算不上源码学习,只是对它其中一些小的开发技巧做一些记录,希望以后在项目开发中能够实践下. 数据层封装 模块只对外暴露mod ...

  2. iOS开发笔记11:表单键盘遮挡、浮点数价格格式化显示、省市区选择器、View Debugging

    1.表单键盘遮挡 应用场景为一个collectionView上有多个textfield.textView供用户填写信息. 之前输入项较少时,采取的方法比较粗暴,didSelectItemAtIndex ...

  3. Express ~ 获取表单 get 和 post 提交方式传送参数的对比

      一,获取 get 提交的参数   var id = req.query.id || ''   二,获取 post 提交的参数 var name = req.body.name || ''

  4. html_表单

    一.表单框架简介 表单是提供让读者在网页上输入,勾选和选取数据,以便提交给服务器数据库的工具.(用于将信息提交给服务器) <form>...</form>标记 作用:用于创建一 ...

  5. from表单实现无跳转上传文件,接收页面后台数据。

    本文基于我刚写的http://www.cnblogs.com/iwang5566/p/6287529.html进行了简单的扩展,实现页面无跳转表单数据提交,并接收后台返回的数据. 下载好,上一篇文章d ...

  6. js02--对象、函数、switch、for、异常、表单验证

    现在我们接着来继续学习有关js的一些基础. 1.undefined与null    undefined:当变量声明但尚未赋值时,它的类型就是undefined    null:表示一个不存在的对象,它 ...

  7. bootstrap基础学习【表单含按钮】(二)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. HTML表单学习

    HTML表单学习 前言 HTML基础学习会由HTML基础标签学习.HTML表单学习和一张思维导图总结HTML基础三篇文章构成,文章中博主会提取出重点常用的知识和经常出现的bug,提高学习的效率,后续会 ...

  9. SpringMVC学习系列(11) 之 表单标签

    本篇我们来学习Spring MVC表单标签的使用,借助于Spring MVC提供的表单标签可以让我们在视图上展示WebModel中的数据更加轻松. 一.首先我们先做一个简单了例子来对Spring MV ...

随机推荐

  1. Silverlight动画之 Animation Easing

    使用Animation Easing函数可以创造出更具有动感的动画.对比下面两个动画. 普通线性动画: <Storyboard x:Name="growStoryboard" ...

  2. 【leetcode】Evaluate Reverse Polish Notation(middle)

    Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...

  3. struts配置文件中如何从一个package的action跳到另一个package中的某个action

    <package name="pack1" namespace="/test1" extends="struts-default"&g ...

  4. 在某公司时的java开发环境配置文档

    1 开发环境配置 1.1.  MyEclipse 配置 1.MyEclipse下载地址:\\server\共享文件\backup\MyEclipse9.0 2.修改工作空间编码为UTF-8,如下图 3 ...

  5. Spetember 5th 2016 Week 37th Monday

    No matter how far you may fly, never forget where you come from. 无论你能飞多远,都别忘了你来自何方. Stay true to you ...

  6. 二叉树计数(codevs 3112)

    题目描述 Description 一个有n个结点的二叉树总共有多少种形态 输入描述 Input Description 读入一个正整数n 输出描述 Output Description 输出一个正整数 ...

  7. eclipse 中添加工程 Some projects cannot be imported because they already exist in the workspace

    第一次从外部文件导入HelloWorld工程到workspace目录中,成功. 删除后,再次从外部导入workspace目录提示 Some projects cannot be imported be ...

  8. ajaxFileUpload上传文件没反应

    调用jquery的ajaxFileUpload异步上传文件,IE浏览器不进入success问题 原因:json转换异常,ie浏览器处理后的返回json没有<pre>标签,直接是完整的jso ...

  9. 二维码相关工具Qrcode笔记

  10. NYOJ题目1049自增自减

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsYAAAN0CAIAAAA4f3koAAAgAElEQVR4nO3dO3LbyNoG4H8TyrUQx1