如何使用Node.js将文件上传到对象存储
介绍
对象存储是一种流行且可扩展的存储和服务静态资产(如音频、图像、文本、PDF 和其他类型的非结构化数据)的方法。 除了用于存储动态应用程序文件和数据库的传统本地或块存储之外,云提供商还提供对象存储。 读对象存储对比 块存储了解用例和两者之间的区别。
Spaces 是 DigitalOcean 提供的简单对象存储服务。 除了能够通过控制面板登录和上传、管理和删除存储的文件外,您还可以通过命令行和 Spaces API 访问您的 DigitalOcean Space。
在本教程中,我们将创建一个 Node.js 应用程序,该应用程序允许用户通过在网站前端提交表单来将文件上传到他们的 DigitalOcean Space。
先决条件
要学习本教程,您需要:
- DigitalOcean Space,以及您帐户的访问密钥和秘密访问密钥。 阅读 如何创建 DigitalOcean 空间和 API 密钥 以使用 DigitalOcean 帐户启动和运行,创建空间,并设置 API 密钥和机密。
- Node.js 和 npm 安装在您的计算机上。 您可以访问 Node.js 下载 为您的操作系统安装正确的版本。
您现在应该有一个 DigitalOcean 帐户,一个带有访问密钥的空间,并且在您的计算机上安装了 Node.js 和 npm。
将访问密钥添加到凭据文件
DigitalOcean Spaces 与 Amazon Simple Storage Service (S3) API 兼容,我们将使用 AWS SDK for JavaScript in Node.js 连接到我们创建的空间。
第一步是创建一个 credentials 文件,用于放置您在创建 DigitalOcean Space 时获得的访问密钥和秘密访问密钥。 该文件将位于 Mac 和 Linux 上的 ~/.aws/credentials 或 Windows 上的 C:\Users\USERNAME\.aws\credentials。 如果您之前保存过 AWS 凭证,您可以阅读有关 保留多组凭证 以获得进一步指导。
打开命令提示符,确保您在 Users 目录中,有权访问管理 sudo
用户,并使用 创建 .aws 目录]credentials 文件里面。
sudo mkdir .aws && touch .aws/credentials
打开文件,将以下代码粘贴到其中,将 your_access_key
和 your_secret_key
替换为各自的密钥。
证书
[default] aws_access_key_id=your_access_key aws_secret_access_key=your_secret_key
现在,您通过 AWS 开发工具包对 Spaces 的访问将通过身份验证,我们可以继续创建应用程序。
安装 Node.js 依赖项
首先,创建一个您想要放置 Node.js 应用程序的目录并导航到该目录。 对于这个演示,我们将在 sites 目录的 spaces-node-app 中创建我们的项目。
mkdir sites/spaces-node-app && cd sites/spaces-node-app
为您的项目创建一个新的 package.json 文件。 将下面的代码粘贴到文件中。
包.json
{ "name": "spaces-node-app", "version": "1.0.0", "main": "server.js", "scripts": { "start": "node server.js" }, "license": "MIT" }
这是一个基本的 package.json
文件,列出了我们应用程序的名称、版本号和许可证。 scripts
字段将允许我们通过键入 npm start
而不是 node server.js
来运行 Node.js 服务器。
我们将使用 npm install
命令安装所有依赖项,然后是项目中四个依赖项的名称。
npm install aws-sdk express multer multer-s3
运行此命令后,应更新 package.json
文件。 这些依赖项将帮助我们连接到 DigitalOcean Spaces API、创建 Web 服务器和处理文件上传。
- aws-sdk — 适用于 JavaScript 的 AWS 开发工具包将允许我们通过 JavaScript API 访问 S3。
- express — Express 是一个 Web 框架,可让我们快速有效地设置服务器。
- multer — Multer 是处理文件上传的中间件。
- multer-s3 — Multer S3 将文件上传扩展到 S3 对象存储,在我们的例子中是 DigitalOcean Spaces。
现在我们已经设置了项目位置和依赖项,我们可以设置服务器和前端视图。
笔记: npm install
saves dependencies to the package.json
file by default in current versions of Node. If you are running an older version of Node, you will have to add the --save
flag to your npm install
command to ensure that package.json
gets updated.
创建应用程序的前端
首先,让我们为应用程序的公共视图创建文件。 这是用户将在前端看到的内容。 在您的项目中创建一个 public 目录,其中包含 index.html
、success.html
和 error.html
。 所有这三个文件都将具有以下 HTML 框架,在 body
中具有不同的内容。 将以下代码写入每个文件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>DigitalOcean Spaces Tutorial</title> <link rel="stylesheet" href="./style.css"> </head> <body> <!-- contents will go here --> </body> </html>
在 error.html
的 body
中写入错误信息。
错误.html
... <h1>Something went wrong!</h1> <p>File was not uploaded successfully.</p> ...
在success.html
的body
中写入成功信息。
成功.html
... <h1>Success!</h1> <p>File uploaded successfully.</p> ...
在 index.html
中,我们将使用 multipart/form-data
创建 HTML form
。 它将由一个简单的文件上传 input
和一个提交按钮组成。
索引.html
... <h1>DigitalOcean Spaces Tutorial</h1> <p>Please select a file and submit the form to upload an asset to your DigitalOcean Space.</p> <form method="post" enctype="multipart/form-data" action="/upload"> <label for="file">Upload a file</label> <input type="file" name="upload"> <input type="submit" class="button"> </form> ...
最后,让我们创建 style.css
并添加足够的 CSS 以使应用程序易于阅读。
样式.css
html { font-family: sans-serif; line-height: 1.5; color: #333; } body { margin: 0 auto; max-width: 500px; } label, input { display: block; margin: 5px 0; }
有了这三个文件,我们就有了一个上传表单,它构成了我们的小应用程序的主页,我们有用户的成功和错误页面。
设置 Express 服务器环境
我们已经为我们的应用程序的前端创建了所有文件,但我们目前没有设置服务器或任何方式来查看它们。 我们将使用 Express Web 框架设置节点服务器。
在项目的根目录下,创建一个server.js
文件。 在顶部,使用 require()
加载我们的四个依赖项。 我们将通过 express
的 app
实例路由我们的应用程序。
服务器.js
// Load dependencies const aws = require('aws-sdk'); const express = require('express'); const multer = require('multer'); const multerS3 = require('multer-s3'); const app = express();
我们的前端位于 public
目录中,因此在依赖项下设置该配置。
服务器.js
... // Views in public directory app.use(express.static('public'));
我们将相对于服务器的根目录路由 index.html
、success.html
和 error.html
。
服务器.js
... // Main, error and success views app.get('/', function (request, response) { response.sendFile(__dirname + '/public/index.html'); }); app.get("/success", function (request, response) { response.sendFile(__dirname + '/public/success.html'); }); app.get("/error", function (request, response) { response.sendFile(__dirname + '/public/error.html'); });
最后,我们将告诉服务器监听哪个端口。 在此示例中,使用了 3001
,但您可以将其设置为任何可用端口。
服务器.js
... app.listen(3001, function () { console.log('Server listening on port 3001.'); });
保存 server.js
并启动服务器。 您可以通过运行 node server.js
或使用 npm start
(我们在 package.json
中设置的快捷方式)来执行此操作。
npm start
Output> node server.js Server listening on port 3001.
导航到 http://localhost:3001
,您将看到上传表单,因为我们将 index.html
设置为服务器的根目录。
您还可以导航到 http://localhost:3001/success
和 http://localhost:3001/error
以确保这些页面正确路由。
使用 Multer 将文件上传到空间
现在我们的服务器环境已启动并正常运行,最后一步是将表单与 Multer 和 Multer S3 集成以将文件上传到 Spaces。
您可以使用 new aws.S3()
连接到 Amazon S3 客户端。 为了与 DigitalOcean Spaces 一起使用,我们需要设置一个新端点以确保它上传到正确的位置。 在撰写本文时,nyc3
是唯一可用于 Spaces 的区域。
在 server.js
中,向上滚动到顶部并将以下代码粘贴到常量声明下方。
服务器.js
... const app = express(); // Set S3 endpoint to DigitalOcean Spaces const spacesEndpoint = new aws.Endpoint('nyc3.digitaloceanspaces.com'); const s3 = new aws.S3({ endpoint: spacesEndpoint });
使用 multer-s3 文档中的示例,我们将创建一个 upload
函数,将 bucket
属性设置为您唯一的空间名称。 将 acl
设置为 public-read
将确保我们的文件可供公众访问; 将此留空将默认为私有,使文件无法从网络访问。
服务器.js
... // Change bucket property to your Space name const upload = multer({ storage: multerS3({ s3: s3, bucket: 'your-space-here', acl: 'public-read', key: function (request, file, cb) { console.log(file); cb(null, file.originalname); } }) }).array('upload', 1);
upload
功能完成,我们的最后一步是将上传表单与代码连接起来,以发送文件并相应地路由用户。 滚动到 server.js
的底部,并将此代码粘贴到文件末尾的 app.listen()
方法的正上方。
服务器.js
... app.post('/upload', function (request, response, next) { upload(request, response, function (error) { if (error) { console.log(error); return response.redirect("/error"); } console.log('File uploaded successfully.'); response.redirect("/success"); }); });
当用户点击提交时,一个 POST 请求会通过 /upload
。 Node 正在监听这个 POST,并调用 upload()
函数。 如果发现错误,条件语句会将用户重定向到 /error
页面。 如果成功,用户将被重定向到/success
页面,文件将被上传到你的空间。
这是 server.js
的完整代码。
服务器.js
// Load dependencies const aws = require('aws-sdk'); const express = require('express'); const multer = require('multer'); const multerS3 = require('multer-s3'); const app = express(); // Set S3 endpoint to DigitalOcean Spaces const spacesEndpoint = new aws.Endpoint('nyc3.digitaloceanspaces.com'); const s3 = new aws.S3({ endpoint: spacesEndpoint }); // Change bucket property to your Space name const upload = multer({ storage: multerS3({ s3: s3, bucket: 'your-space-here', acl: 'public-read', key: function (request, file, cb) { console.log(file); cb(null, file.originalname); } }) }).array('upload', 1); // Views in public directory app.use(express.static('public')); // Main, error and success views app.get('/', function (request, response) { response.sendFile(__dirname + '/public/index.html'); }); app.get("/success", function (request, response) { response.sendFile(__dirname + '/public/success.html'); }); app.get("/error", function (request, response) { response.sendFile(__dirname + '/public/error.html'); }); app.post('/upload', function (request, response, next) { upload(request, response, function (error) { if (error) { console.log(error); return response.redirect("/error"); } console.log('File uploaded successfully.'); response.redirect("/success"); }); }); app.listen(3001, function () { console.log('Server listening on port 3001.'); });
通过在命令提示符下键入 CONTROL
+ C
停止 Node 服务器,然后重新启动它以确保应用新的更改。
npm start
导航到项目的根目录,选择一个文件,然后提交表单。 如果一切设置正确,您将被重定向到成功页面,并且您的 DigitalOcean Space 上将提供一个公共文件。
假设您上传的文件是 test.txt
,则文件的 URL 将是 https://your-space-here.nyc3.digitaloceanspaces.com/test.txt
。
交易不成功的常见原因是凭据错误、凭据文件位于错误位置或存储桶名称不正确。
结论
恭喜,您已经设置了一个 Node.js 和 Express 应用程序来将静态资产上传到对象存储!
您可以通过 在此处重新混合项目 来使用此 DigitalOcean Spaces 节点应用程序的代码。
必须采取其他预防措施(例如身份验证)才能将此类应用程序投入生产,但这是使您的 Web 应用程序与 DigitalOcean Spaces 一起运行的良好起点。 有关对象存储的更多信息,请阅读 DigitalOcean Spaces 简介。