Node.js實現檔案上傳,node.js檔案上傳

來源:互聯網
上載者:User

Node.js實現檔案上傳,node.js檔案上傳

在工作中碰到了這樣的需求,需要用nodejs 來上傳檔案,之前也只是知道怎麼通過瀏覽器來上傳檔案, 用nodejs的話, 相當於類比瀏覽器的行為。 google 了一番之後, 明白了瀏覽器無非就是利用http協議來給伺服器傳輸資料, 具體協議就是《RFC 1867 - Form-based File Upload in HTML》, 在瀏覽器上通過form 表單來上傳檔案就是通過這個協議,我們可以先看看瀏覽器給服務端發送了什麼資料, 就可以依葫蘆畫瓢的把上傳功能實現出來。說起form 表單上傳檔案的話, 大家應該很熟悉:

<form action="http://www.qq.com/" method="post"><input type="text" name="text1" /><br /><input type="text" name="text2" /><br /><input type="submit" /></form> 

提交時, 用fiddler 抓包可以看到向服務端發出這樣的資料:

POST http://www.qq.com/ HTTP/1.1
Host: www.qq.com
Content-Length: 23
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

text1=hello&text2=world

值得注意的是Content-Type預設為application/x-www-form-urlencoded,所以訊息會經過URL編碼。比如“你好”會編碼為 %E4%BD%A0%E5%A5%BD。

接下來我們看一下通過form 表單是怎麼上傳的。大家應該也不陌生:

<form action="http://www.qq.com" method="post" enctype="multipart/form-data"><input type="file" name="myfile" /><input type="submit" value="submit" /></form>

然後建立一個只有hello world字樣的upload.txt文字檔上傳上去,我們再吃用fiddler 來抓下包, 可以發現發送過去的資料稍微複雜了一些(已經去掉了很多的其它沒關係的請求行,比如緩衝控制和cookie之類的):

POST http://www.qq.com/ HTTP/1.1
Host: www.qq.com
Content-Length: 199
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywr3X7sXBYQQ4ZF5G

------WebKitFormBoundarywr3X7sXBYQQ4ZF5G
Content-Disposition: form-data; name="myfile"; filename="upload.txt"
Content-Type: text/plain

hello world

------WebKitFormBoundarywr3X7sXBYQQ4ZF5G--

根據RFC 1867的定義,我們需要產生一段邊界資料,這個資料不能在內容的其它地方出現,這個可以自己定義, 在每個瀏覽器的產生演算法可能都不一樣, 上面的boundary就是分隔資料,產生了分隔資料之後, 就可以把分隔資料放在頭部的Content-Type裡面傳送給服務端, 也就是上文的 Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywr3X7sXBYQQ4ZF5G, 另外,上傳的內容,需要用分隔資料來分隔成若干個段,然後每段資料裡面都有檔案的檔案名稱,還有上傳時候的name,服務端就是用這個name來接收檔案,還有檔案的類型Content-Type,在這個例子裡是 text/plain,如果上傳的是png圖片就是image/png。檔案類型的一個空行後就是所上傳的檔案的內容,在這個例子裡也是為了容易理解所以上傳的是文字檔所以內容直接就能夠顯示出來,如果上傳的是圖片檔案, 因為是二進位檔案,fiddler 就顯示的是亂碼。 檔案的內容結束之後就是一個空行再加上邊界資料。

瞭解了發送格式的細節之後, 下一步就是使用nodejs來編程實現,簡單來講, 就是按照格式把資料發送給服務端就行了。

const http = require('http');const fs = require('fs');//post地址為本地服務的一個php,用於測試上傳是否成功var options = {hostname: 'localhost',port: 80,path: '/get.php',method: 'POST'}//產生分隔資料var boundaryKey = '----WebKitFormBoundaryjLVkbqXtIi0YGpaB'; //讀取需要上傳的檔案內容fs.readFile('./upload.txt', function (err, data) {//拼裝分隔資料區段var payload = '--' + boundaryKey + '\r\n' + 'Content-Disposition:form-data; name="myfile"; filename="upload.txt"\r\n' + 'Content-Type:text/plain\r\n\r\n';payload += data;payload += '\r\n--' + boundaryKey + '--';//發送請求var req = http.request(options, function (res) {res.setEncoding('utf8');res.on('data', function (chunk) {console.log('body:' + chunk);});});req.on('error', function(e) {console.error("error:"+e);});//把boundary、要發送的資料大小以及資料本身寫進請求req.setHeader('Content-Type', 'multipart/form-data; boundary='+boundaryKey+'');req.setHeader('Content-Length', Buffer.byteLength(payload, 'utf8'));req.write(payload);req.end();});

本文重點在於瞭解協議並且用代碼實現出來, 程式碼群組織上面還有很多最佳化的地方。

最後在本地apache,簡單寫一個php來儲存上傳的檔案來用作測試:

<?php$filePath = './upload.txt';move_uploaded_file($_FILES['myfile']['tmp_name'] , $filePath);echo "ok";?>

另外,根據RFC 1867 還可以實現一次上傳多個檔案的功能, 這個在這裡就不詳述, 需要的話可以詳細參考RFC 1867來實現。

以上所述是小編給大家介紹的Node.js實現檔案上傳,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對幫客之家網站的支援!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.