成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Node.js 小知識 — 實現圖片上傳寫入磁盤的接口

開發 前端
開啟一個 Node.js 服務,指定路由 /upload/image 收到請求后調用 uploadImageHandler 方法,傳入 Request 對象。

 [[373386]]

一:開啟 Node.js 服務

開啟一個 Node.js 服務,指定路由 /upload/image 收到請求后調用 uploadImageHandler 方法,傳入 Request 對象。

  1. const http = require('http'); 
  2. const formidable = require('formidable'); 
  3. const fs = require('fs'); 
  4. const fsPromises = fs.promises; 
  5. const path = require('path'); 
  6. const PORT = process.env.PORT || 3000; 
  7. const server = http.createServer(async (req, res) => { 
  8.   if (req.url === '/upload/image' &&  req.method.toLocaleLowerCase() === 'post') { 
  9.     uploadImageHandler(req, res); 
  10.   } else { 
  11.    res.setHeader('statusCode', 404); 
  12.    res.end('Not found!'
  13.   } 
  14. }); 
  15. server.listen(PORT, () => { 
  16.   console.log(`server is listening at ${server.address().port}`); 
  17. }); 

二:處理圖片對象

formidable 是一個用來處理上傳文件、圖片等數據的 NPM 模塊,form.parse 是一個 callback 轉化為 Promise 便于處理。

Tips:拼接路徑時使用 path 模塊的 join 方法,它會將我們傳入的多個路徑參數拼接起來,因為 Linux、Windows 等不同的系統使用的符號是不同的,該方法會根據系統自行轉換處理。

  1. const uploadImageHandler = async (req, res) => { 
  2.   const form = new formidable.IncomingForm({ multiples: true });   
  3.   form.encoding = 'utf-8';   
  4.   form.maxFieldsSize = 1024 * 5;   
  5.   form.keepExtensions = true
  6.  
  7.   try { 
  8.     const { file } = await new Promise((resolve, reject) => {   
  9.       form.parse(req, (err, fields, file) => {   
  10.         if (err) {   
  11.           return reject(err);   
  12.         } 
  13.  
  14.          return resolve({ fields, file });   
  15.       });   
  16.     }); 
  17.     const { name: filename, path: sourcePath } = file.img; 
  18.     const destPath = path.join(__dirname, filename); 
  19.     console.log(`sourcePath: ${sourcePath}. destPath: ${destPath}`); 
  20.     await mv(sourcePath, destPath); 
  21.     console.log(`File ${filename} write success.`); 
  22.     res.writeHead(200, { 'Content-Type''application/json' }); 
  23.     res.end(JSON.stringify({ code: 'SUCCESS', message: `Upload success.`})); 
  24.   } catch (err) { 
  25.     console.error(`Move file failed with message: ${err.message}`); 
  26.     res.writeHead(200, { 'Content-Type''application/json' }); 
  27.     res.end(JSON.stringify({ code: 'ERROR', message: `${err.message}`})); 
  28.   } 

三:實現 mv 方法

fs.rename 重命名文件

將上傳的圖片寫入本地目標路徑一種簡單的方法是使用 fs 模塊的 rename(sourcePath, destPath) 方法,該方法會異步的對 sourcePath 文件做重命名操作,使用如下所示:

  1. const mv = async (sourcePath, destPath) => { 
  2.  return fsPromises.rename(sourcePath, destPath); 
  3. }; 

cross-device link not permitted

在使用 fs.rename() 時還要注意 cross-device link not permitted 錯誤,參考 rename(2) — Linux manual page:

**EXDEV **oldpath and newpath are not on the same mounted filesystem. (Linux permits a filesystem to be mounted at multiple points, but rename() does not work across different mount points, even if the same filesystem is mounted on both.)

oldPath 和 newPath 不在同一掛載的文件系統上。(Linux 允許一個文件系統掛載到多個點,但是 rename() 無法跨不同的掛載點進行工作,即使相同的文件系統被掛載在兩個掛載點上。)

在 Windows 系統同樣會遇到此問題,參考 http://errorco.de/win32/winerror-h/error_not_same_device/0x80070011/

winerror.h 0x80070011 #define ERROR_NOT_SAME_DEVICE The system cannot move the file to a different disk drive.(系統無法移動文件到不同的磁盤驅動器。)

此處在 Windows 做下復現,因為在使用 formidable 上傳文件時默認的目錄是操作系統的默認目錄 os.tmpdir(),在我的電腦上對應的是 C 盤下,當我使用 fs.rename() 將其重名為 F 盤時,就出現了以下報錯:

  1. C:\Users\ADMINI~1\AppData\Local\Temp\upload_3cc33e9403930347b89ea47e4045b940 F:\study\test\202366 
  2. [Error: EXDEV: cross-device link not permitted, rename 'C:\Users\ADMINI~1\AppData\Local\Temp\upload_3cc33e9403930347b89ea47e4045b940' -> 'F:\study\test\202366'] { 
  3.   errno: -4037, 
  4.   code: 'EXDEV'
  5.   syscall: 'rename'
  6.   path: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\upload_3cc33e9403930347b89ea47e4045b940'
  7.   dest: 'F:\\study\\test\\202366' 

設置源路徑與目標路徑在同一磁盤分區

設置上傳文件中間件的臨時路徑為最終寫入文件的磁盤分區,例如我們在 Windows 測試時將圖片保存在 F 盤下,所以設置 formidable 的 form 對象的 uploadDir 屬性為 F 盤,如下所示:

  1. const form = new formidable.IncomingForm({ multiples: true });   
  2. form.uploadDir = 'F:\\' 
  3. form.parse(req, (err, fields, file) => {   
  4.   ... 
  5. }); 

這種方式有一定局限性,如果寫入的位置位于不同的磁盤空間該怎么辦呢?

可以看下下面的這種方式。

讀取-寫入-刪除臨時文件

一種可行的辦法是讀取臨時文件寫入到新的位置,最后在刪除臨時文件。所以下述代碼創建了可讀流與可寫流對象,使用 pipe 以管道的方式將數據寫入新的位置,最后調用 fs 模塊的 unlink 方法刪除臨時文件。

  1. const mv = async (sourcePath, destPath) => { 
  2.   try { 
  3.     await fsPromises.rename(sourcePath, destPath); 
  4.   } catch (error) { 
  5.     if (error.code === 'EXDEV') { 
  6.       const readStream = fs.createReadStream(sourcePath);   
  7.       const writeStream = fs.createWriteStream(destPath); 
  8.       return new Promise((resolve, reject) => { 
  9.         readStream.pipe(writeStream); 
  10.         readStream.on('end', onClose); 
  11.         readStream.on('error', onError); 
  12.         async function onClose() { 
  13.           await fsPromises.unlink(sourcePath); 
  14.           resolve(); 
  15.         } 
  16.         function onError(err) { 
  17.           console.error(`File write failed with message: ${err.message}`);   
  18.           writeStream.close(); 
  19.           reject(err) 
  20.         } 
  21.       }) 
  22.     } 
  23.  
  24.     throw error; 
  25.   } 

四:測試

方式一:終端調用

  1. curl --location --request POST 'localhost:3000/upload/image' \ 
  2. --form 'img=@/Users/Downloads/五月君.jpeg' 

方式二:POSTMAN 調用

Reference

  • https://github.com/andrewrk/node-mv/blob/master/index.js
  • https://stackoverflow.com/questions/43206198/what-does-the-exdev-cross-device-link-not-permitted-error-mean/43206506#43206506
  • https://nodejs.org/api/fs.html#fs_fs_rename_oldpath_newpath_callback

本文轉載自微信公眾號「 Nodejs技術棧  」,可以通過以下二維碼關注。轉載本文請聯系 Nodejs技術棧公眾號。

 

責任編輯:武曉燕 來源: Nodejs技術棧
相關推薦

2011-09-08 14:16:12

Node.js

2021-03-09 08:03:21

Node.js 線程JavaScript

2025-05-26 00:31:31

2021-09-26 22:22:42

js模塊Node

2013-11-01 09:34:56

Node.js技術

2015-03-10 10:59:18

Node.js開發指南基礎介紹

2021-12-25 22:29:57

Node.js 微任務處理事件循環

2012-02-03 09:25:39

Node.js

2020-05-29 15:33:28

Node.js框架JavaScript

2021-07-16 04:56:03

NodejsAddon

2011-11-10 08:55:00

Node.js

2012-10-24 14:56:30

IBMdw

2011-09-08 13:46:14

node.js

2011-11-01 10:30:36

Node.js

2011-09-02 14:47:48

Node

2011-09-09 14:23:13

Node.js

2014-11-04 09:54:00

Node.jsWeb

2011-10-25 09:28:30

Node.js

2021-09-26 05:06:04

Node.js模塊機制

2021-11-06 18:40:27

js底層模塊
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品国产欧美一区二区三区成人 | 久草欧美视频 | 黄色免费在线观看 | 日韩精品av一区二区三区 | av色站| 日韩三级在线 | 91中文字幕在线 | 久久久久国产精品一区二区 | 蜜桃视频麻豆 | 日韩欧美三级电影 | 日韩一区在线播放 | 天天操天天插 | 亚洲欧洲在线观看视频 | 欧美黄色性生活视频 | 国产精品毛片av | 中文字幕精品一区 | 国产 日韩 欧美 在线 | 久久精品免费一区二区三 | 婷婷综合五月天 | 日韩欧美在线播放 | 亚洲天堂999 | 精精精精xxxx免费视频 | 黄网免费看| 日批免费看 | 婷婷在线视频 | 91国内精品久久 | 国产真实乱全部视频 | 日韩欧美国产综合 | 成人精品一区二区三区中文字幕 | 在线观看黄色电影 | 2019天天干夜夜操 | 欧美亚洲一区二区三区 | 色999视频 | 精品国产欧美一区二区三区不卡 | 久久久精彩视频 | 国产精品一二三区 | 免费黄网站在线观看 | 午夜精品视频在线观看 | 91黄在线观看 | 日韩成人在线网站 | 日韩欧美在线观看视频网站 |