• express-10 表单处理


    从用户那里收集信息的常用方法就是使用HTML表单。无论是使用浏览器提交表单,还是使用AJAX提交,或是运用精巧的前端控件,底层机制通常仍旧是HTML表单。

    向服务器发送客户端数据###

    向服务器发送客户端数据有两种方式:查询字符串和请求正文。通常,如果是使用查询字符串,就发起了一个GET请求;如果是使用请求正文,就发起了一个POST请求。

    有一种普遍的误解是POST请求是安全的,而GET请求不安全。事实上如果使用HTTPS协议,两者都是安全的;如果不使用,则都不安全。如果不使用HTTPS协议,入侵者会像查看GET请求的查询字符串一样,轻松查看POST请求的报文数据。然而,如果你使用GET请求,用户会在查询字符串中看到所有的输入数据(包括隐藏域)。此外,浏览器会限制查询字符串的长度(对请求正文没有长度限制)。基于这些原因,一般推荐使用POST进行表单提交。

    HTML表单###

    例子:

    <form action="/process" method="POST">
       <input type="hidden" name="hush" val="hidden, but not secret!">
       <div>
          <label for="fieldColor">Your favorite color: </label>
          <input type="text" id="fieldColor" name="color">
       </div>
       <div>
          <button type="submit">Submit</button>
       </div>
    </form>
    

    请注意,在<form>标记中提交方法被明确地指定为POST:如果不这么做,默认进行GET提交。action的值被指定为用于接收表单数据的URL。如果你忽略这个值,表单会提交到它被加载进来时的同一URL。我建议你始终都为action提供一个有效值,即使是使用AJAX提交(这会防止你丢失数据)

    从服务器的角度来看,最重要的属性是<input>域中的name属性,这样服务器才能识别字段。name属性与id属性是截然不同的,后者只适用于样式和前端功能(它不会发送到服务器端)。

    HTML并不会限制在同一个页面上有多个表单(遗憾的是有些早期服务器框架有限制,比如ASP)。建议保持表达逻辑上的一致性:一个表单应该只包含想要提交的字段。如果一个页面上有两个不同的action,请使用两个不同的表单。例如,在一个页面上一个表单用于网站搜索,另一个表单用于登录获得电子简讯。只用一个大表单是可行的,可以根据用户点击的按钮判断采用哪个action,但是这会让人头疼,而且通常对于残疾人是不友好的(由于无障碍浏览器呈现表单的方式)。

    当用户提交表单时,/process URL被请求,字段值在请求正文中被传输到服务器。

    编码###

    当表单被提交(通过浏览器或AJAX)时,某种程度上它必须被编码。如果不明确地指定编码,则默认为application/x-wwwform-urlencoded(这只是一个冗长的用于“URL编码”的媒体类型)。它是受Express支持的基本、易用的编码。

    如果需要上传文件,事情就开始变得复杂起来。使用URL编码很难发送文件,所以不得不使用multipart/form-data编码类型,这并不直接由Express处理(事实上,Express仍然支持这种编码,但是在Express的下一个版本它会被移除,并且它也并不被建议使用)。

    处理表单的不同方式###

    如果不使用AJAX,唯一的选择是用浏览器提交表单,这会重新加载页面。然而,如何重新加载页面由你来决定。处理表单时有两件事需要考虑:处理表单是哪个路径(action),以及向浏览器发出怎样的响应。

    如果表单使用的是method="POST"(推荐使用),那么展现表单和处理表单通常使用相同的路径:这样可以区分开来,因为前者是一个GET请求,而后者是一个POST请求。如果采用这种方法,就可以省略表单上的action属性。

    无论使用什么路径来处理表单,必须决定如何响应浏览器。

    • 直接响应HTML

    处理表单之后,可以直接向浏览器返回HTML(例如,一个视图)。如果用户尝试重新加载页面,这种方法就会产生警告,并且会影响书签和后退按钮。基于这些原因,不推荐这种方法。

    • 302重定向:

    虽然这是一种常见的方法,但这是对响应代码302本义的滥用。HTTP 1.1增加了响应代码303,一种更合适的代码。除非你有理由让浏览器回到1996年,否则你应该改用303。

    • 303重定向:

    HTTP 1.1添加了响应代码303用来解决302重定向的滥用。HTTP规范明确地表明浏览器303重定向后,无论之前是什么方法,都应该使用GET请求。这是用于响应表单提交请求的推荐方法。

    由于推荐通过303重定向来响应表单提交,接下来的问题是:“重定向指向哪里?”。下面是一些常用的方法。

    • 重定向到专用的成功/失败页面

    这种方法需要为适当的成功或失败消息提供URL。例如,如果一个用户通过促销邮件注册,但是有一个数据库错误,可能希望重定向到/error/database。如果用户的电子邮件地址是无效的,可以重定向到/error/invalid-email。如果一切顺利,可以重定向到/promo-email/thank-you。这种方法的一个优点是便于分析:访问/promo-email/thank-you页面的人数应该和登录促销邮件的人数大致相关。而且这种方法也很容易实现。然而它还有一些缺点。这意味着你必须针对每一种可能性来分配URL,这也意味着页面设计、编写复制和维护。另一个缺点是用户体验欠佳

    • 运用flash消息重定向到原位置

    由于有许多小表单分散在整个站点中(例如,电子邮件登录),最好的用户体验是不干扰用户的导航流。也就是说,需要一个不用离开当前页面就能提交表单的方法。当然,要做到这一点,可以用AJAX,但是如果你不想用AJAX(或者你希望备用机制能够提供一个好的用户体验),可以重定向回用户之前浏览的页面。最简单的方法是在表单中使用一个隐藏域来存放当前URL。因为你想有一种反馈,表明用户的提交信息已收到,所以你可以使用flash消息。

    • 运用flash消息重定向到新位置

    大型表单通常都会有自己的页面,一旦提交就没有必要停留在这个页面上了。在这种情况下,就要考虑一下用户接下来想去哪儿,并相应地进行重定向。

    如果使用AJAX,推荐使用专门的URL。

    Express表单处理###

    如果使用GET进行表单处理,表单域在req.query对象中。如果使用POST(推荐使用的),需要引入中间件来解析URL编码体。

    • 首先,安装body-parser中间件(npm install --save body-parser),然后引入:
    var bodyParser = require('body-parser');
    app.use(bodyParser());
    

    有时,你会发现有些地方不鼓励使用express.bodyParser,并且理由充分。然而,这个问题在Epress 4.0中消失了,body-parser中间件是安全的并且推荐使用。

    • 创建/views/newsletter.handlebars
    <h2>Sign up for our newsletter to receive news and specials!</h2>
    <form class="form-horizontal" 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>
    
    • 应用文件
    app.get('/newsletter', function(req, res){
        //我们会在后面学到CSRF……目前, 只提供一个虚拟值
        res.render('newsletter', { csrf: 'CSRF token goes here' });
    });
    
    app.post('/process', function(req, res){
        console.log('Form (from querystring): ' + req.query.form);
        console.log('CSRF token (from hidden form field): ' + req.body._csrf);
        console.log('Name (from visible form field): ' + req.body.name);
        console.log('Email (from visible form field): ' + req.body.email);
        res.redirect(303, '/thank-you');
    });
    

    在处理程序中,我们将重定向到“thank you”视图。我们可以在此渲染视图,但是如果这样做,访问者的浏览器地址栏仍旧是/process,这可能会令人困惑。发起一个重定向可以解决这个问题。

    在这种情况下使用303(或302)重定向,而不是301重定向,这一点非常重要。301重定向是“永久”的,意味着浏览器会缓存重定向目标。如果使用301重定向并且试图第二次提交表单,浏览器会绕过整个/process处理程序直接进入/thank you页面,因为它正确地认为重定向是永久性的。另一方面,303重定向告诉浏览器“是的,你的请求有效,可以在这里找到响应”,并且不会缓存重定向目标。

  • 相关阅读:
    PHP识别二维码功能,php-zbarcode 安装
    《架构即未来》读后感(三)
    MVC设计模式案例分析
    SOA
    《架构即未来》读后感(二)
    基于网络拓扑及告警的故障根因定位系统实现及算法研究赛题需求分析
    《架构即未来》读后感(一)
    《大型网站技术架构》读后感(二)
    《一线架构师实践指南》读后感(三)
    《大型网站技术架构》读后感(三)
  • 原文地址:https://www.cnblogs.com/jinkspeng/p/4281488.html
Copyright © 2020-2023  润新知