首頁 >web前端 >js教程 >用Node處理檔案上傳

用Node處理檔案上傳

不言
不言原創
2018-07-07 17:15:493107瀏覽

這篇文章主要介紹了關於用Node處理文件上傳,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

前言

在Web開發中,文件上傳是一個非常常見、非常重要的功能。本文將介紹如何用Node處理上傳的檔案。

需求分析

由於現在前後端分離很流行,那麼本文也直接採用前後端分離的做法。前端介面如下:
用Node處理檔案上傳

使用者從瀏覽器中選擇文件,點擊上傳,將發起http請求到伺服器,伺服器將接受到的文件儲存在伺服器硬碟中。

前端部分

ajax請求庫採用axios,為了簡化說明,前端限制上傳的文件類型只能為圖片,且一次只能上傳一張,有興趣的朋友可以自行補充,程式碼如下:

nbsp;html>


  <meta>
  <title>Title</title>
  <script></script>


  <input>
  <button>上传</button>

  <script>
    let file = &#39;&#39;
    let fileName = &#39;&#39;

    function submit() {
      let data = new FormData()
      data.append(&#39;imgName&#39;, fileName)
      data.append(&#39;img&#39;, file)

      axios({
        method: &#39;post&#39;,
        timeout: 2000,
        url: &#39;http://localhost:3000/postApi&#39;,
        data: data
      })
        .then(response => {
          console.log(response.data)
        })
        .catch(error => {
          console.log(error)
        })
    }

    function changeImg(e) {
      file = e.target.files.item(0)
      // 如果不选择图片
      if (file === null) {
        return
      }
      fileName = file.name
    }
  </script>

後端部分

這是本文要介紹的重點,為了用高效流暢的方式來解析文件上傳請求,我們先引入formidable函式庫:

npm install formidable --save

formidable的串流解析器讓它成為了處理檔案上傳的絕佳選擇,也就是說它能隨著資料區塊的上傳接收它們,解析它們,並吐出特定的部分,相信熟悉流的朋友會很好理解。這種方式不僅快,還不會因為需要大量緩衝而導致記憶體膨脹,即便像視訊這種大型文件,也不會把進程壓垮。
首先,我們在根目錄下創建myImage文件,用於存放上傳的圖片(注意:如果沒有創建,會導致上傳報錯),接著,我們創建一個IncomingForm實例form,並且設置存放路徑為myImage文件夾。程式碼如下:

var http = require('http')
var formidable = require('formidable')

var server = http.createServer(function(req, res){
  // 1 设置cors跨域
  res.setHeader('Access-Control-Allow-Origin', '*')
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
  res.setHeader('Content-Type', 'application/json')

  // 2
  switch (req.method) {
    case 'OPTIONS':
      res.statusCode = 200
      res.end()
      break
    case 'POST':
      upload(req, res)
      break
  }
})

function upload(req, res) {
  // 1 判断
  if (!isFormData(req)) {
    res.statusCode = 400
    res.end('错误的请求, 请用multipart/form-data格式')
    return
  }

  // 2 处理
  var form = new formidable.IncomingForm()
  form.uploadDir = './myImage'
  form.keepExtensions = true

  form.on('field', (field, value) => {
    console.log(field)
    console.log(value)
  })
  form.on('end', () => {
    res.end('上传完成!')
  })

  form.parse(req)
}

function isFormData(req) {
  let type = req.headers['content-type'] || ''
  return type.includes('multipart/form-data')
}

server.listen(3000)
console.log('port is on 3000.')

node app開啟http伺服器後,在前端頁面中上傳一張kitty.jpg,我們看到控制台列印了前端上傳的imgName屬性:kitty.jpg
用Node處理檔案上傳

並且,myImage資料夾目錄下多了一張圖片:
用Node處理檔案上傳

開啟一看,正是從前端上傳的那張kitty.jpg

檔案改名

我們發現,這個預設的檔案名稱並不是我們想要的,我們想改成以當前時間戳命名的文件,新增的功能代碼如下:

  var fs = require('fs')

  form.on('file', (name, file) => {
    // 重命名文件
    let types = file.name.split('.')
    let suffix = types[types.length - 1]
    fs.renameSync(file.path, './myImage/' + new Date().getTime() + '.' + suffix)
  })

再次上傳,發現現在存的照片名稱已經變成我們想要的格式了。
用Node處理檔案上傳

新增上傳進度

Formidable的progress事件能給予收到的位元組數,以及期望收到的位元組數。我們可以藉助這個做出一個進度條。
我們為上面的程式添加下面的程式碼,每次有progress事件激發,就會計算百分比並用console.log()輸出:

  form.on('progress', (bytesReceived, bytesExpected) => {
    var percent = Math.floor(bytesReceived / bytesExpected * 100)
    console.log(percent)
  })

再次上傳一張圖片,現在控制台已經會列印出進度顯示了:
用Node處理檔案上傳

當然,一般情況下,我們是要把這個進度傳回用戶的瀏覽器中去,這對於任何想要上傳大型文件的程序來說是個很棒的特性,而且這是個很適合用Node完成的任務。比如說用WebSocket協議,或是像Socket.IO這樣的即時模組,關於Node中使用websocket,後面我會單獨出一篇文章來介紹。

錯誤處理

任何時候都不要忘了對程式添加錯誤處理,如果你的程式在重要的時候崩掉了,可能輕則被老闆打屁股,重則拉出去祭天。想像一下,如果用戶上傳的圖片很大,而且用戶的網路還很慢,那麼上傳的時間會超出前端程式碼中設定的請求超時時間2s,伺服器就會崩掉,不信?我們來試試一下。
首先,我選擇了一張很大的圖片,5M,並且用chrome瀏覽器將瀏覽器網絡環境設置為slow 3g,設定方法如下:
f12打開開發者工具,在more tools-- network conditions
用Node處理檔案上傳

用Node處理檔案上傳

點擊上傳,我們看見服務端控制台的資訊如下,伺服器崩掉了:
用Node處理檔案上傳

所以,最后我们加上了错误处理,代码如下:

  // 加上错误处理,防止用户网络慢,或者取消上传,导致服务器崩掉
  form.on('error', err => {
    console.log(err)
    res.statusCode = 500
    res.end('服务器内部错误!')
  })

小结

现在,相信你已经学会了如何用Node处理文件上传了,结合前面的那篇用Node提供静态文件服务的文章,你是不是能够自己摸索着去尝试做一些有趣的事情了呢?

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

JS浏览器事件循环机制

小程序中使用ECharts 异步加载数据

以上是用Node處理檔案上傳的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn