如何在 Node.js 中使用 FilePond
譯文【51CTO.com快譯】上傳文件是云應用程序的常見需求。FilePond是一個可靠的開源項目,它為React和Svelte等許多 JavaScript 框架提供了復雜的文件處理和包裝器。
本文詳細地概述了使用 FilePond 、 Node.js 和 Express 后端處理文件上傳。
為什么要使用FilePond?
有許多庫可用于文件上傳,但 FilePond 非常易于使用,并且無需額外配置即可處理圖像優化等細節。此外,它在服務器端為開發人員提供了一個清晰的流程。
再加上對 Angular、jQuery、React、Vue 和 Svelte 的支持以及圖像預覽和縮放器等眾多插件,FilePond在考慮文件上載時應該位于選項列表的頂部。
設置 FilePond 項目
首先設置一個項目來保存示例代碼。創建一個目錄并將其命名為 /filepond。然后轉到命令行上的目錄并鍵入npm init. 接受所有默認值。
下一步使用npm install Express安裝Express服務器。接下來,創建一個 index.html 文件并將其放在項目根目錄中。使用清單 1 的內容來更新新文件。
清單 1. 開始 index.html
- <html>
- <head>
- <link href="https://unpkg.com/filepond/dist/filepond.css" rel="stylesheet" />
- <script src="https://unpkg.com/filepond/dist/filepond.js"></script>
- </head>
- <body>
- <input type="file">
- </body>
- <script>
- const inputElement = document.querySelector('input[type="file"]');
- const pond = FilePond.create( inputElement );
- </script>
- </html>
清單 1 首先從 unpkg CDN 中導入 FilePond 樣式和代碼。還可以通過 npm 和構建工具集成或直接導入它。
標記僅包含一個文件輸入。最后,底部的腳本獲取對文件輸入的引用,然后使用FilePond API使用輸入元素FilePond.create(inputElement)創建一個新的FilePond實例。
現在將添加一個腳本來運行應用程序。修改 package.json 文件以包含清單 2 中的第 7 行。
清單 2. 添加開發(dev)腳本
- {
- "name": "filepond",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "dev": "nodemon server.js",
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "author": "",
- "license": "ISC",
- "dependencies": {
- "express": "^4.17.1"
- }
- }
通過在CLI中鍵入nodemon-v,確保全局安裝了nodemon。如果找不到,請使用npm install -g nodemon.
現在,可以在項目根目錄下輸入npm run dev來運行應用程序。
在應用程序運行時,可以通過打開瀏覽器訪問http://localhost:43000/來訪問簡單的起始頁。
將會看到一個簡單的文件輸入組件。盡管 FilePond 尚未綁定到后端,但可以繼續從本地文件系統中選擇一個文件,方法是單擊“瀏覽”或將文件拖到 FilePond 組件上,FilePond 將按照順序進行為其排隊。
處理文件上傳
與后端交互的第一步是告訴 FilePond 的位置在哪里。FilePond 可以處理任何 URL。在本例子中,我們將使用來自同一域的相對路徑。如果使用指向另一個域的絕對 URL,那么CORS將發揮作用。
修改 index.html 中的腳本以包含清單 3 中所示的配置。
清單 3. 設置服務器 URL
- <script>
- const inputElement = document.querySelector('input[type="file"]');
- const pond = FilePond.create( inputElement );
- pond.setOptions({
- server: "/upload"
- })
- </script>
清單 3 告訴 FilePond (通過 POST)將文件位發送到相對 URL /upload。讓我們在服務器上準備一個簡單的處理程序來驗證端點是否被命中。將清單 4 中的代碼添加到 index.js 文件中。
清單 4. 映射 /upload POST
- app.post("/upload", function(req, res){
- console.log("BEGIN /upload");
- })
然后返回瀏覽器并刷新頁面。當上傳文件時,可以通過查看服務器日志并查看“BEGIN /upload”輸出來驗證是否正在訪問端點。
保存臨時文件
上傳文件時,服務器首先將文件臨時寫入某個位置。服務器用唯一 ID 響應以確認上傳,當客戶端提交包含文件輸入的表單時,它將包含唯一 ID。然后,服務器使用唯一 ID 來定位臨時文件并將該文件移動到其長期位置。
也可以采用多種不同的方法來支持服務器端的這些需求,同時使用文件系統和數據庫。
本示例將使用Formidable庫來處理 FilePond 發送的多部分 POST。Formidable 是一個成熟且功能強大的庫,它的靈活性足以編寫自定義流處理程序。例如,如果想將文件保存到數據庫中,可以自己處理文件塊并將它們流式傳輸到數據存儲。
在本演示中,只需將簡單地將臨時文件寫入磁盤。首先安裝 Formidable:停止服務器(如果正在運行)并鍵入npm install formidable. 現在您可以重新啟動服務器。
轉到 index.js 并通過在文件開頭插入以下行來導入庫:
const formidable = require('formidable');
然后使用清i單 5 更新ndex.js。
清單 5. 接受臨時文件
- app.post("/upload", function(req, res){
- console.log("BEGIN /upload");
- const form = formidable({ multiples: false });
- form.parse(req, (err, fields, files) => {
- if (err) {
- next(err);
- return;
- }
- let theFile = files.filepond.path;
- console.log("theFile: " + theFile);
- res.writeHead(200, { 'Content-Type': 'text/plain' });
- res.end(theFile);
- });
- })
使用 Formidable接受文件是輕而易舉的。如果通過 Web 界面上傳文件,將在日志記錄中看到該文件已寫入默認的臨時文件位置。例如,在我的本地系統上,即 C:\Users\mtyson\AppData\Local\Temp\。即可以打開文件并驗證它是你發送的文件。
請注意,應用程序使用文件路徑發送純文本響應。這在現實場景中是不安全的,因為最終用戶可以看到文件結構并收集有關系統的信息(就像我的文件路徑顯示它是 Windows 系統一樣)。
對于生產用途,需要一個間接層,以便保存文件并創建一個與文件路徑相關聯的唯一 ID。出于安全的目的,我們將只使用文件路徑。
完成文件上傳
現在回到客戶端。將上傳器包裝在一個表單中并提交,并考慮將文件保存在何處以供長期存儲。由于表單僅發送文件的路徑(或唯一 ID),因此可以將其作為帶有 JSON 的 AJAX 請求輕松處理。保持文件傳輸的簡單性,并在示例中使用表單提交,如清單 6 所示。
清單 6. uploader表單
- <body>
- <form style="display:grid;" action="/save" method="POST">
- <input type="file">
- <button type="submit" onclick="">Save It</button>
- </form>
- </body>
現在,當單擊按鈕時,將提交文件路徑,默認標簽為“filepond”(這是可配置的)。在這種情況下,我們通過 POST 將信息發送到 /save。
請注意,如果將文件輸入設置為“多個支持”,FilePond 將處理排隊的多個文件。
要處理提交,返回 index.js 并使用 Express urlencoded 中間件:
- app.use(express.urlencoded({ extended: true }));
現在就可以準備好接收文件信息。添加如清單 7 所示的處理程序。
清單 7. 接收保存
- app.post("/save", function(req, res){
- console.log("BEGIN /save");
- console.log(`req: ${JSON.stringify(req.body)}`);
- })
清單 7 中的處理程序就位后,應該可以看到日志以確認信息已經到達。日志記錄將如下所示:
- req: {"filepond":"C:\\Users\\mtyson\\AppData\\Local\\Temp\\upload_28331577a229fe48443275b2655a1abe"}
現在,可以從磁盤讀取該文件并對其執行所需操作。使用 Node 的內置 fs 模塊從磁盤讀取它,如清單 8 所示。
清單 8. 從磁盤讀取臨時文件
- const fs =要求( 'fs' ); //...讓fileData = fs . readFileSync ( req . body . filepond );
清單 8 創建了文件的緩沖區對象。當然也可以使用Amazon上的ODFS或bucket將文件寫入另一個系統(如Amazon上的一個模塊)。
例如,在 MongoDB 中,可以按原樣獲取緩沖區并將其寫入如下字段:
- require('mongodb').Binary(fileData)
這總結了上傳和保存文件的完整周期。我們將看看圖像預覽器擴展。
將圖像預覽器添加到應用程序很簡單,如清單 9 所示。
清單 9. 圖像預覽器插件
- <head>
- ...
- <script src="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.js"></script>
- <link href="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css" rel="stylesheet">
- </head>
- <body>
- ...
- FilePond.registerPlugin(FilePondPluginImagePreview);
- ...
- </body>
當你上傳一個圖像文件時,你將看到一個預覽,如圖1所示。
圖1.圖像預覽器
正如你所看到的,FilePond在一個易于使用的API中提供了一個現代的文件上傳器組件。還有許多其他FilePond插件可用,包括一個完整的圖像編輯器(通過與Pintura/Doka集成)。
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】