ノードを0から1まで学ぶ(2) httpサーバーを構築する

大家讲道理
リリース: 2017-01-24 15:40:40
オリジナル
1170 人が閲覧しました

前回の授業前学習では、さまざまなモジュール仕様間の接続と違いについて学びました。このセクションでは、正式にノードの学習を開始します。まず、簡単なプログラムを実行できる http サーバーを構築します。

1. hello world

最も古典的な hello world。まず、server.js を作成してコードを保存します: hello world。首先我们创建一个server.js来保存我们的代码:

console.log( 'hello world' );
ログイン後にコピー

在终端输入node server.js运行:

node server.js
ログイン後にコピー
ログイン後にコピー

终端就会输出 hello world 的字样。可是我们一个node服务器程序,总是要在浏览器上访问的呀,这里就要用到node里自带的http模块了:

var http = require('http'); // 引入http模块// 创建http服务器// request : 从浏览器带来的请求信息// response : 从服务器返回给浏览器的信息http.createServer(function(request, response){
    response.writeHead(200, {'content-type': 'text/plain'}); // 设置头部信息,输出text文本
    response.write('hello world'); // 输出到页面中的信息
    response.end(); // 返回结束}).listen(3000);console.log('server has started...');
ログイン後にコピー

我们再次在终端输入node server.js运行,终端里会有输出 server has started… 的字样,表示服务器已创建并正在运行,然后我们在浏览器上访问127.0.0.1:3000,就可以看到页面中输出了hello world

2. form表单

刚才我们只是在页面中输出了一段简单的文本,现在我们要在页面中呈现一个表单,可以让用户输入信息并进行提交:

// server.js
var http = require('http');

http.createServer(function(request, response){
var html = &#39;<html>\    <head>\    <meta charset=UTF-8" />\    </head>\    <body>\    <form action="/" method="post">\    <p>username : <input type="text" name="username" /></p>\    <p>password : <input type="password" name="password" /></p>\    <p>age : <input type="text" name="age" /></p>\    <p><input type="submit" value="submit" name="submit" /></p>\    </form>\    </body>\    </html>&#39;;

    response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;}); // 输出html头信息
    response.write(html); // 将拼接的html字符串输出到页面中
    response.end(); // 结束
}).listen(3000);
console.log(&#39;server has started...&#39;);
ログイン後にコピー

修改server.js中的内容,重新运行:

node server.js
ログイン後にコピー
ログイン後にコピー

刷新页面后,我们发现页面中输出了3个文本框和1个提交按钮。因为我们的程序只是呈现页面,并没有做任何其他的处理,因此在页面中提交数据只是刷新当前页面。

注意: 我们每次修改node中的任何代码后,都要重新进行启动。

2.1 获取表单GET方式提交的数据

我们上面的代码中使用的是POST方式,不过这里要先讨论使用GET方式提交过来的数据,我们先不考虑数据的安全性,只是学习如何获取使用get方式提交过来的form表单数据,将post改为get,重新运行。

我们知道,使用get方式提交数据,会将数据作为URL参数传递过来,因此我们通过解析URL中的参数获取到数据,这里就用到了url模块中的方法:

// server.js
var http = require(&#39;http&#39;),
url = require(&#39;url&#39;);

http.createServer(function(request, response){
    var html = &#39;<html>\        <head>\        <meta charset=UTF-8" />\        </head>\        <body>\        <form action="/" method="get">\        <p>username : <input type="text" name="username" /></p>\        <p>password : <input type="password" name="password" /></p>\        <p>age : <input type="text" name="age" /></p>\        <p><input type="submit" value="submit" name="submit" /></p>\        </form>\        </body>\        </html>&#39;;
    
    var query = url.parse( request.url, true ).query;
    if( query.submit ){
        var data = &#39;<p><a href="/">back</a></p>&#39;+
            &#39;<p>username:&#39;+query.username+&#39;</p>&#39;+
            &#39;<p>password:&#39;+query.password+&#39;</p>&#39;+
            &#39;<p>age:&#39;+query.age+&#39;</p>&#39;;
         
        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
        response.write(data);
    }else{
        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
        response.write(html);
    }
    response.end(); // 结束
}).listen(3000);
console.log(&#39;server has started...&#39;);
ログイン後にコピー

我们再次运行提交后就能在页面中显示出数据了。

url.parse是用来解析URL字符串的,并返回解析后的URL对象。若我们只输出一下 url.parse(request.url) :

url.parse(request.url);
result:
Url {
    protocol: null,   
     slashes: null,   
      auth: null,    
      host: null,    
      port: null,    
      hostname: null,    
      hash: null,    
      search: &#39;?username=111113&password=123&age=122&submit=submit&#39;,    
      query: &#39;username=111113&password=123&age=122&submit=submit&#39;,   
       pathname: &#39;/&#39;,    
       path: &#39;/?username=111113&password=123&age=122&submit=submit&#39;,    
       href: &#39;/?username=111113&password=123&age=122&submit=submit&#39;
       }
ログイン後にコピー

如果将第2个参数设置为true,则会将返回结果中的query属性解析为一个对象,其他属性不变;默认值为false,即query属性是一个字符串:

url.parse(request.url, true);result:Url {
...
query: {
    username: &#39;111113&#39;,
    password: &#39;123&#39;,
    age: &#39;122&#39;,
    submit: &#39;submit&#39; },
...
}
ログイン後にコピー

因此我们可以通过如下语句判断是否有提交数据并获取提交数据,然后再输出到中即可:

var query = url.parse( request.url, true ).query;
/*
{
    username: &#39;111113&#39;,
    password: &#39;123&#39;,
    age: &#39;122&#39;,
    submit: &#39;submit&#39;}
*/
ログイン後にコピー

2.2 获取表单POST方式提交的数据

现在我们使用post方式来提交数据。因为POST请求一般都比较“重” (用户可能会输入大量的内容),如果用阻塞的方式来处理处理,必然会导致用户操作的阻塞。因此node将post数据拆分为很多小的数据块,然后通过data事件(表示新的小数据块到达了)和end事件传递这些小数据块(表示所有的数据都已经接收完毕)。 所以,我们的思路应该是:在data事件中获取数据块,在end事件中操作数据。

// server.js
var http = require(&#39;http&#39;),
querystring = require(&#39;querystring&#39;);

http.createServer(function(request, response){
    var html = &#39;<html>\        <head>\        <meta charset=UTF-8" />\        </head>\        <body>\        <form action="/" method="post">\        <p>username : <input type="text" name="username" /></p>\        <p>password : <input type="password" name="password" /></p>\        <p>age : <input type="text" name="age" /></p>\        <p><input type="submit" value="submit" name="submit" /></p>\        </form>\        </body>\        </html>&#39;;
    
    if( request.method.toLowerCase()==&#39;post&#39; ){
        var postData = &#39;&#39;;

        request.addListener(&#39;data&#39;, function(chunk){
            postData += chunk;
        });

        request.addListener(&#39;end&#39;, function(){
            var data = querystring.parse(postData);
            console.log( &#39;postData: &#39;+postData );
            console.log(data);
    
            var s = &#39;<p><a href="/">back</a></p>&#39;+
                &#39;<p>username:&#39;+data.username+&#39;</p>&#39;+
                &#39;<p>password:&#39;+data.password+&#39;</p>&#39;+
                &#39;<p>age:&#39;+data.age+&#39;</p>&#39;;

            response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
            response.write(s);
            response.end();
        })
    }else{
        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
        response.write(html);
        response.end();
    }
}).listen(3000);
console.log(&#39;server has started...&#39;);
ログイン後にコピー

这段代码与上段代码项目,主要有的几个变化是:

  1. 不再引入url模块, 改用引入querystring模块。因为我们不再对URL进行操作了,也没必要引入了;

  2. 使用request.method.toLowerCase()==&#39;post&#39;判断当前是否有数据提交;

  3. 在data事件进行数据的拼接,在end事件中进行的处理;

  4. response.end()写在了end事件内部,因为end事件是异步操作,因此必须得数据输出完成之后才能执行response.end()

    &#39;username=123&password=123&age=23&submit=submit&#39;;
    ログイン後にコピー
ターミナルに node server.js< と入力します。 /code>Run:<p></p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">// starter.js 页面初始化 function start(request, response){ var html = &amp;#39;&lt;html&gt;\ &lt;head&gt;\ &lt;meta charset=UTF-8&quot; /&gt;\ &lt;/head&gt;\ &lt;body&gt;\ &lt;form action=&quot;/show&quot; method=&quot;post&quot;&gt;\ &lt;p&gt;username : &lt;input type=&quot;text&quot; name=&quot;username&quot; /&gt;&lt;/p&gt;\ &lt;p&gt;password : &lt;input type=&quot;password&quot; name=&quot;password&quot; /&gt;&lt;/p&gt;\ &lt;p&gt;age : &lt;input type=&quot;text&quot; name=&quot;age&quot; /&gt;&lt;/p&gt;\ &lt;p&gt;&lt;input type=&quot;submit&quot; value=&quot;submit&quot; name=&quot;submit&quot; /&gt;&lt;/p&gt;\ &lt;/form&gt;\ &lt;/body&gt;\ &lt;/html&gt;&amp;#39;; response.writeHead(200, {&quot;Content-Type&quot;:&quot;text/html&quot;}); response.write( html ); response.end(); } exports.start = start;</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div><div class="highlighter-rouge"></div> ターミナルは<strong>hello world</strong>という単語を出力します。ただし、ノード サーバー プログラムには常にブラウザ上でアクセスする必要があります。ここでは、ノードに付属する <code class="highlighter-rouge">http モジュールを使用する必要があります: 🎜🎜
// uploader.js 展示获取的数据var querystring = require(&#39;querystring&#39;);function upload(request, response){    var postData = &#39;&#39;;

    request.addListener(&#39;data&#39;, function(chunk){
      postData += chunk;
    });
    
    request.addListener(&#39;end&#39;, function(){        var data = querystring.parse(postData);        console.log( &#39;postData: &#39;+postData );        console.log(data);        var s = &#39;<p><a href="/">back</a></p>&#39;+            &#39;<p>username:&#39;+data.username+&#39;</p>&#39;+            &#39;<p>password:&#39;+data.password+&#39;</p>&#39;+            &#39;<p>age:&#39;+data.age+&#39;</p>&#39;;

        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
        response.write(s);
        response.end();
    })
}
exports.upload = upload;
ログイン後にコピー
ログイン後にコピー
🎜 🎜 と入力します。ターミナルで class="highlighter-rouge">node server.js を再度実行すると、「server has starting…」というメッセージがターミナルに出力され、サーバーが作成されたことが示されます。が実行されているので、ブラウザで 127.0.0.1:3000 にアクセスすると、ページに hello が出力されることがわかります。世界。 🎜🎜2. フォーム🎜🎜 ここまでは単純なテキストをページに出力しただけですが、今度はユーザーが情報を入力して送信できるフォームをページに表示します。 🎜🎜
// server.jsvar http = require(&#39;http&#39;),
url = require(&#39;url&#39;);

http.createServer(function(request, response){    var pathname = url.parse(request.url).pathname;    console.log(pathname);
    response.end();
}).listen(3000);console.log(&#39;server has started...&#39;);
ログイン後にコピー
ログイン後にコピー
🎜🎜server.js コンテンツを変更します。 -run: 🎜🎜
http://127.0.0.1:3000/ // 输出: /
http://127.0.0.1:3000/show/ // 输出: /show/
http://127.0.0.1:3000/show/img/ // 输出: /show/img/
http://127.0.0.1:3000/show/?username=wenzi // 输出: /show/
ログイン後にコピー
ログイン後にコピー
🎜🎜 ページを更新した後、ページ上に 3 つのテキスト ボックスと 1 つの送信ボタンが出力されていることがわかりました。このプログラムはページをレンダリングするだけで他の処理は行わないため、ページ内のデータを送信すると現在のページが更新されるだけです。 🎜🎜注: ノード内のコードを変更するたびに、ノードを再起動する必要があります。 🎜

2.1 フォームの GET メソッドで送信されたデータを取得する

🎜 上記のコードでは POST メソッドを使用していますが、ここではまず GET メソッドの使用について説明します。 メソッド 送信されたデータについては、現時点ではデータのセキュリティは考慮していません。get メソッドを使用して送信されたフォーム データを取得し、post を get に変更して再度実行する方法を学習します。 🎜🎜 get メソッドを使用してデータを送信すると、データが URL パラメータとして渡されることがわかっているため、URL 内のパラメータを解析することでデータを取得します。ここでは url</code を使用します。 >モジュール内のメソッド: 🎜🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">// server.jsvar http = require(&amp;#39;http&amp;#39;), url = require(&amp;#39;url&amp;#39;), starter = require(&amp;#39;./starter&amp;#39;), uploader = require(&amp;#39;./uploader&amp;#39;); http.createServer(function(request, response){ var pathname = url.parse(request.url).pathname; var routeurl = { &amp;#39;/&amp;#39; : starter.start, &amp;#39;/show&amp;#39; : uploader.upload } if( typeof routeurl[pathname]=== &amp;#39;function&amp;#39; ){ routeurl[pathname](request, response); }else{ console.log(&amp;#39;404 not found!&amp;#39;); response.end(); } }).listen(3000);console.log(&amp;#39;server has started...&amp;#39;);</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div>🎜🎜 送信を再度実行すると、データがページに表示されます。 🎜🎜url.parse は、URL 文字列を解析し、解析された URL オブジェクトを返すために使用されます。 url.parse(request.url) のみを出力する場合: 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">npm install formidable --save-dev</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div>🎜 2 番目のパラメーターが true に設定されている場合、返された結果のクエリ属性はオブジェクトに解析され、他の属性は変更されません。 false 、つまり、クエリ属性は文字列です: 🎜🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:bash;toolbar:false">// starter.js function start(request, response){ var html = &amp;#39;&lt;html&gt;\ &lt;head&gt;\ &lt;meta charset=UTF-8&quot; /&gt;\ &lt;/head&gt;\ &lt;body&gt;\ &lt;form action=&quot;/upload&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;\ &lt;p&gt;file : &lt;input type=&quot;file&quot; name=&quot;upload&quot; multiple=&quot;multiple&quot; /&gt;&lt;/p&gt;\ &lt;p&gt;&lt;input type=&quot;submit&quot; value=&quot;submit&quot; name=&quot;submit&quot; /&gt;&lt;/p&gt;\ &lt;/form&gt;\ &lt;/body&gt;\ &lt;/html&gt;&amp;#39;; response.writeHead(200, {&quot;Content-Type&quot;:&quot;text/html&quot;}); response.write( html ); response.end(); } exports.start = start;</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div>🎜🎜 したがって、次のステートメントを使用して、送信されたデータがあるかどうかを判断し、送信されたデータを取得し、それを次のように出力できます: 🎜🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:bash;toolbar:false;">// uploader.jsvar formidable = require(&amp;#39;formidable&amp;#39;), util = require(&amp;#39;util&amp;#39;), fs = require(&amp;#39;fs&amp;#39;);function upload(request, response){ if( request.method.toLowerCase()==&amp;#39;post&amp;#39; ){ var form = new formidable.IncomingForm(); form.uploadDir = &amp;#39;./tmp/&amp;#39;; form.parse(request, function(err, fields, files) { var oldname = files.upload.name, newname = Date.now() + oldname.substr(oldname.lastIndexOf(&amp;#39;.&amp;#39;)); fs.renameSync(files.upload.path, &quot;./img/&quot;+newname ); // 上传到 img 目录 response.writeHead(200, {&amp;#39;content-type&amp;#39;: &amp;#39;text/plain&amp;#39;}); response.write(&amp;#39;received upload:\n\n&amp;#39;); response.end(util.inspect({fields: fields, files: files})); }); return; } } exports.upload = upload;</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div>🎜<h4 >2.2 フォームの取得 POST メソッド送信データ</h4>🎜今度は post メソッドを使用してデータを送信します。 POST リクエストは一般に「重い」(ユーザーが大量のコンテンツを入力する可能性がある) ため、ブロック的な方法で処理されると、必然的にユーザー操作のブロックにつながります。したがって、ノードはポスト データを多くの小さなデータ ブロックに分割し、データ イベント (新しい小さなデータ ブロックが到着したことを示す) と終了イベント (すべてのデータが受信されたことを示す) を通じてこれらの小さなデータ ブロックを配信します。 したがって、データイベントでデータブロックを取得し、終了イベントでデータを操作するという考え方になります。 🎜🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:bash;toolbar:false;">received upload: { fields: { // 其他控件,如input, textarea等 submit: &amp;#39;submit&amp;#39;}, files:{ // file控件 upload:{ domain: null, _events: {}, _maxListeners: undefined, size: 5097, path: &amp;#39;tmp\upload_b1f7c3e83af224e9f3a020958cde5dcd&amp;#39;, name: &amp;#39;chrome.png&amp;#39;, type: &amp;#39;image/png&amp;#39;, hash: null, lastModifiedDate: Thu Jan 12 2017 23:09:50 GMT+0800 (中国标准时间), _writeStream: [Object] } } }</pre><div class="contentsignin">ログイン後にコピー</div></div>🎜🎜このコードと前のコード プロジェクトの間の主な変更点は次のとおりです: 🎜<ol class="list-paddingleft-2"><li>🎜 URL モジュールは導入されなくなり、代わりにクエリ文字列モジュールが導入されました。 。 URL はもう運用されていないため、導入する必要はありません 🎜🎜<li>🎜<code class="highlighter-rouge">request.method.toLowerCase()=='post' を使用してください。現在送信されたデータがあるかどうかを判断します 🎜🎜
  • 🎜 データは data イベントに結合され、end イベントで処理されます 🎜🎜
  • 🎜response.end ()end イベント内に記述されます。end イベントは非同期操作であるため、 は実行されるまで実行できません。データの出力が完了しました。response.end()🎜🎜🎜🎜postData が次のような文字列であることがわかります:🎜🎜
    // shower.jsvar fs = require(&#39;fs&#39;),
    url = require(&#39;url&#39;);function show(request, response){    var query = url.parse(request.url, true).query,
            imgurl = query.src;    // 读取图片并进行输出
        // 这里读取链接中的src参数,指定读取哪张图片  /show?src=1484234660592.png
        fs.readFile(&#39;./img/&#39;+imgurl, "binary", function(err, file){         if(err) throw err;
            response.writeHead(200, {"Content-Type": "image/png"});
            response.write(file, "binary");
            response.end();
        })
    }
    exports.show = show;
    ログイン後にコピー
    ログイン後にコピー
    🎜

    因此我们使用query.parse将postData解析为对象类型,以便获取提交过来的数据。

    3. 路由

    现在我们所有的逻辑都是在根目录下进行的,没有按照url区分,这里我们按照功能进行路由拆分。以上面的post请求为例,我们可以拆分为:页面初始化和form提交后的处理。

    页面初始化:

    // starter.js  页面初始化
    
    function start(request, response){
        var html = &#39;<html>\        <head>\        <meta charset=UTF-8" />\        </head>\        <body>\        <form action="/show" method="post">\        <p>username : <input type="text" name="username" /></p>\        <p>password : <input type="password" name="password" /></p>\        <p>age : <input type="text" name="age" /></p>\        <p><input type="submit" value="submit" name="submit" /></p>\        </form>\        </body>\        </html>&#39;;
        
        response.writeHead(200, {"Content-Type":"text/html"});
        response.write( html );
        response.end();
    }
    exports.start = start;
    ログイン後にコピー
    ログイン後にコピー

    展示获取的数据:

    // uploader.js 展示获取的数据var querystring = require(&#39;querystring&#39;);function upload(request, response){    var postData = &#39;&#39;;
    
        request.addListener(&#39;data&#39;, function(chunk){
          postData += chunk;
        });
        
        request.addListener(&#39;end&#39;, function(){        var data = querystring.parse(postData);        console.log( &#39;postData: &#39;+postData );        console.log(data);        var s = &#39;<p><a href="/">back</a></p>&#39;+            &#39;<p>username:&#39;+data.username+&#39;</p>&#39;+            &#39;<p>password:&#39;+data.password+&#39;</p>&#39;+            &#39;<p>age:&#39;+data.age+&#39;</p>&#39;;
    
            response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
            response.write(s);
            response.end();
        })
    }
    exports.upload = upload;
    ログイン後にコピー
    ログイン後にコピー

    然后在server.js中进行路由选择

    // server.jsvar http = require(&#39;http&#39;),
    url = require(&#39;url&#39;);
    
    http.createServer(function(request, response){    var pathname = url.parse(request.url).pathname;    console.log(pathname);
        response.end();
    }).listen(3000);console.log(&#39;server has started...&#39;);
    ログイン後にコピー
    ログイン後にコピー

    我们任意改变URL地址,会看到输出的每个地址的pathname(忽略/favicon.ico):

    http://127.0.0.1:3000/ // 输出: /
    http://127.0.0.1:3000/show/ // 输出: /show/
    http://127.0.0.1:3000/show/img/ // 输出: /show/img/
    http://127.0.0.1:3000/show/?username=wenzi // 输出: /show/
    ログイン後にコピー
    ログイン後にコピー

    因此我们就根据pathname进行路由,对路由进行方法映射:

    // server.jsvar http = require(&#39;http&#39;),
    url = require(&#39;url&#39;),
    starter = require(&#39;./starter&#39;),
    uploader = require(&#39;./uploader&#39;);
    
    http.createServer(function(request, response){    var pathname = url.parse(request.url).pathname;    var routeurl = {        &#39;/&#39; : starter.start,        &#39;/show&#39; : uploader.upload
        }    if( typeof routeurl[pathname]=== &#39;function&#39; ){
            routeurl[pathname](request, response);
        }else{        console.log(&#39;404 not found!&#39;);
            response.end();
        }
    }).listen(3000);console.log(&#39;server has started...&#39;);
    ログイン後にコピー
    ログイン後にコピー

    如果匹配到路由 / ,则执行 starter.start(request, response) ;如果匹配到路由 /show ,则执行 uploader.upload(request, response) 。如果都没匹配到,则显示404。

    4. 图片上传并显示

    在上面我们已经能成功提交数据了,这里来讲解如何进行图片上传并显示。使用node自带的模块处理起来非常的麻烦,这里我们使用别人已经开发好的formidable模块进行编写,它对解析上传的文件数据做了很好的抽象。

    npm install formidable --save-dev
    ログイン後にコピー
    ログイン後にコピー

    在starter.js中,我们添加上file控件:

    // starter.js
    function start(request, response){
        var html = &#39;<html>\
            <head>\
            <meta charset=UTF-8" />\
            </head>\
            <body>\
            <form action="/upload" method="post" enctype="multipart/form-data">\
            <p>file : <input type="file" name="upload" multiple="multiple" /></p>\
            <p><input type="submit" value="submit" name="submit" /></p>\
            </form>\
            </body>\
            </html>&#39;;
        response.writeHead(200, {"Content-Type":"text/html"});
        response.write( html );
        response.end();
    }
    exports.start = start;
    ログイン後にコピー
    ログイン後にコピー

    4.1 图片上传

    首先我们进行的是图片上传操作,首先我们要确保当前目录中存在tmp和img目录。在 uploader.js 中:

    // uploader.jsvar formidable = require(&#39;formidable&#39;),
    util = require(&#39;util&#39;),
    fs = require(&#39;fs&#39;);function upload(request, response){    if( request.method.toLowerCase()==&#39;post&#39; ){        var form = new formidable.IncomingForm();
    
            form.uploadDir = &#39;./tmp/&#39;;
            form.parse(request, function(err, fields, files) {            var oldname = files.upload.name,
                    newname = Date.now() + oldname.substr(oldname.lastIndexOf(&#39;.&#39;));
                fs.renameSync(files.upload.path, "./img/"+newname ); // 上传到 img 目录
    
                response.writeHead(200, {&#39;content-type&#39;: &#39;text/plain&#39;});
                response.write(&#39;received upload:\n\n&#39;);
                response.end(util.inspect({fields: fields, files: files}));
            });        return;
        }
    }
    exports.upload = upload;
    ログイン後にコピー
    ログイン後にコピー

    我们上传图片后跳转到upload路径,然后显示出相应的信息:

    received upload:
    
    {
        fields: { // 其他控件,如input, textarea等
        submit: &#39;submit&#39;},
    files:{ // file控件
        upload:{
                domain: null,
                _events: {},
                _maxListeners: undefined,
                size: 5097,
                path: &#39;tmp\\upload_b1f7c3e83af224e9f3a020958cde5dcd&#39;,
                name: &#39;chrome.png&#39;,
                type: &#39;image/png&#39;,
                hash: null,
                lastModifiedDate: Thu Jan 12 2017 23:09:50 GMT+0800 (中国标准时间),
                _writeStream: [Object]
            }
        }
    }
    ログイン後にコピー

    我们再查看img目录时,就会发现我们刚才上传的照片了。

    4.2 图片显示

    将图片上传到服务器后,怎样才能把图片显示在浏览器上呢。这里我们就使用到了fs模块来读取文件,创建一个shower.js来专门展示图片:

    // shower.jsvar fs = require(&#39;fs&#39;),
    url = require(&#39;url&#39;);function show(request, response){    var query = url.parse(request.url, true).query,
            imgurl = query.src;    // 读取图片并进行输出
        // 这里读取链接中的src参数,指定读取哪张图片  /show?src=1484234660592.png
        fs.readFile(&#39;./img/&#39;+imgurl, "binary", function(err, file){         if(err) throw err;
            response.writeHead(200, {"Content-Type": "image/png"});
            response.write(file, "binary");
            response.end();
        })
    }
    exports.show = show;
    ログイン後にコピー
    ログイン後にコピー

    然后在 server.js 中添加上 show 的路由映射:

    var routeurl = {  
      &#39;/&#39; : starter.start,   
       &#39;/upload&#39; : uploader.upload,  
       &#39;/show&#39; : shower.show 
       // 添加
       };
    ログイン後にコピー


    最后在 upload.js 中进行图片的引用:

    form.parse(request, function(err, fields, files) {    var oldname = files.upload.name,
            newname = Date.now() + oldname.substr(oldname.lastIndexOf(&#39;.&#39;));
        fs.renameSync(files.upload.path, "./img/"+newname ); // 同步上传图片
    
        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});    var s = &#39;<p><a href="/">back</a></p><p><img src="/show?src=&#39;+newname+&#39;" /></p>&#39;; // 显示刚才的图片
        response.write(s);
        response.end();
    });
    ログイン後にコピー

    5. 综合

    刚才学习了上传数据和上传图片,这里我们将其综合一下,拟定一个题目:“设定用户名密码,并上传头像”。希望可以自己实现一下。

    6. 接口的实现

    在第2部分学习了GET和POST请求,那么在这里写一个简单json或jsonp接口应该不是什么难事儿了吧。

    创建一个 inter.js :

    // inter.jsvar url = require(&#39;url&#39;);function init(request, response){    if( request.method.toLowerCase()==&#39;get&#39; ){        var query = url.parse(request.url, true).query;        var data = {"code":0, "msg":"success", "data":[{"username":"wenzi", "age":26}, {"username":"bing", "age":25}]};        if( query && query.callback ){            // jsonp
                response.end( query.callback + &#39;(&#39; + JSON.stringify(data) + &#39;)&#39; );
             }else{            // json
                response.end( JSON.stringify(data) );
            }
        }
    }
    exports.init = init;
    ログイン後にコピー

    在server中添加inter的引用和路由映射:

    var routeurl = {    &#39;/&#39; : starter.start,    &#39;/upload&#39; : uploader.upload,    &#39;/show&#39; : shower.show,    &#39;/inter&#39; : inter.init // 添加};
    ログイン後にコピー

    然后对 http://127.0.0.1:3000/inter 进行json请求或jsonp请求即可。

    7. 总结

    这节还是写了不少的内容,最核心的就是讲解如何搭建一个简单的http服务器,进行数据和图片的提交与处理,在最后稍微讲了下接口的编写,后面有机会的话,会再具体讲解下接口的编写。


  • 関連ラベル:
    ソース:php.cn
    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
    最新の問題
    人気のチュートリアル
    詳細>
    最新のダウンロード
    詳細>
    ウェブエフェクト
    公式サイト
    サイト素材
    フロントエンドテンプレート
    私たちについて 免責事項 Sitemap
    PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!