通过 IoT 中心将设备中的文件上传到云 (Node.js)
本文演示 IoT 中心的文件上传功能如何使用 Node.js 将文件上传到 Azure Blob 存储。
将遥测数据从设备发送到 IoT 中心快速入门和使用 IoT 中心发送云到设备的消息一文介绍了 IoT 中心提供的基本的设备到云和云到设备的消息传送功能。 使用 IoT 中心配置消息路由教程介绍了一种在 Azure Blob 存储中可靠存储设备到云消息的方法。 但是,在某些情况下,无法轻松地将设备发送的数据映射为 IoT 中心接受的相对较小的设备到云消息。 例如:
- 视频
- 包含图像的大型文件
- 以高频率采样的振动数据
- 某种形式的预处理数据。
通常使用 Azure 数据工厂或 Hadoop 堆栈等工具在云中批处理这些文件。 需要从设备上传文件时,仍可以使用 IoT 中心的安全性和可靠性。 本文介绍如何进行此操作。
在本文结束时,会运行两个 Node.js 控制台应用:
FileUpload.js,它使用 IoT 中心提供的 SAS URI 将文件上传到存储。
FileUploadNotification.js,它接收来自 IoT 中心的文件上传通知。
注意
IoT 中心通过 Azure IoT 设备 SDK 来支持许多设备平台和语言(包括 C、Java、Python 和 JavaScript)。 请参阅 Azure IoT 开发人员中心,了解如何将设备连接到 Azure IoT 中心。
重要
使用 X.509 证书颁发机构 (CA) 身份验证的设备上的文件上传功能为公共预览版,并且必须启用预览模式。 这是在一同使用 X.509 指纹身份验证或 X.509 证书证明与 Azure 设备预配服务的设备上的正式发布版本。 若要了解有关使用 IoT 中心进行 x.509 身份验证的详细信息,请参阅支持的 x.509 证书。
先决条件
已注册的设备。 在 Azure 门户中注册一个。
Node.js 版本 10.0.x 或更高版本。 建议使用 LTS 版本。 可以从 nodejs.org 下载 Node.js。
端口 8883 在防火墙中须处于打开状态。 本文中的设备示例使用 MQTT 协议,该协议通过端口 8883 进行通信。 在某些公司和教育网络环境中,此端口可能被阻止。 有关解决此问题的更多信息和方法,请参阅连接到 IoT 中心(MQTT)。
将 Azure 存储帐户关联到 IoT 中心
若要从设备上传文件,必须拥有与 IoT 中心关联的 Azure 存储帐户和 Azure Blob 存储容器。 将存储帐户和容器与 IoT 中心关联后,IoT 中心可以在设备请求时提供 SAS URI 的元素。 然后,设备可以使用这些元素来构造 SAS URI,并将其用于向 Azure 存储进行身份验证,以及上传文件到 blob 容器。
将 Azure 存储帐户与 IoT 中心关联:
在“中心设置”下,选择 IoT 中心左侧窗格上的“文件上传”。
在“文件上传”窗格中,选择“Azure 存储容器” 。 对于本文,建议你的存储帐户和 IoT 中心位于同一区域。
如果你已有要使用的存储帐户,请从列表中选择它。
若要创建新的存储帐户,请选择“+存储帐户”。 为该存储帐户命名,并确保其位置设置为 IoT 中心的同一区域,然后选择“确定” 。 将在 IoT 中心的同一资源组中创建新帐户。 部署完成后,从列表中选择“存储帐户”。
选择“存储帐户”后,将打开“容器”窗格。
在“容器”窗格中,选择“blob 容器”。
如果已有要使用的 blob 容器,请从列表中选择它,然后单击“选择”。
然后选择“新建容器”以创建新的 blob 容器。 为新容器命名。 出于本文的目的,可以将其他所有字段保留为默认值。 选择“创建”。 部署完成后,从列表中选择“容器”,然后单击“选择”。
回到“文件上传”窗格,确保文件通知设置为“开启” 。 可将其他所有设置保留默认值。 选择“保存”并等待设置完成,然后进入下一部分。
有关如何创建 Azure 存储帐户的详细说明,请参阅创建存储帐户。 若要了解如何将存储帐户以及 blob 容器与 IoT 中心关联的详细信息,请参阅使用 Azure 门户配置文件上传。
从设备应用上传文件
在本部分,我们创建将文件上传到 IoT 中心的设备应用。 该代码基于 Azure IoT Node.js SDK 设备示例中的 upload_to_blob_advanced.js 示例中提供的代码。
创建名为
fileupload
的空文件夹。 在fileupload
文件夹的命令提示符处,使用以下命令创建 package.json 文件。 接受所有默认值:npm init
在
fileupload
文件夹的命令提示符处,运行以下命令来安装 azure-iot-device 设备 SDK、azure-iot-device-mqtt 和 @azure/storage-blob 包:npm install azure-iot-device azure-iot-device-mqtt @azure/storage-blob --save
使用文本编辑器,在
fileupload
文件夹中创建一个 FileUpload.js 文件,并将以下代码复制到其中。'use strict'; const Client = require('azure-iot-device').Client; const Protocol = require('azure-iot-device-mqtt').Mqtt; const errors = require('azure-iot-common').errors; const path = require('path'); const { AnonymousCredential, BlockBlobClient, newPipeline } = require('@azure/storage-blob'); // make sure you set these environment variables prior to running the sample. const deviceConnectionString = process.env.DEVICE_CONNECTION_STRING; const localFilePath = process.env.PATH_TO_FILE; const storageBlobName = path.basename(localFilePath); async function uploadToBlob(localFilePath, client) { const blobInfo = await client.getBlobSharedAccessSignature(storageBlobName); if (!blobInfo) { throw new errors.ArgumentError('Invalid upload parameters'); } const pipeline = newPipeline(new AnonymousCredential(), { retryOptions: { maxTries: 4 }, telemetry: { value: 'HighLevelSample V1.0.0' }, // Customized telemetry string keepAliveOptions: { enable: false } }); // Construct the blob URL to construct the blob client for file uploads const { hostName, containerName, blobName, sasToken } = blobInfo; const blobUrl = `https://${hostName}/${containerName}/${blobName}${sasToken}`; // Create the BlockBlobClient for file upload to the Blob Storage Blob const blobClient = new BlockBlobClient(blobUrl, pipeline); // Setup blank status notification arguments to be filled in on success/failure let isSuccess; let statusCode; let statusDescription; try { const uploadStatus = await blobClient.uploadFile(localFilePath); console.log('uploadStreamToBlockBlob success'); // Save successful status notification arguments isSuccess = true; statusCode = uploadStatus._response.status; statusDescription = uploadStatus._response.bodyAsText; // Notify IoT Hub of upload to blob status (success) console.log('notifyBlobUploadStatus success'); } catch (err) { isSuccess = false; statusCode = err.code; statusDescription = err.message; console.log('notifyBlobUploadStatus failed'); console.log(err); } await client.notifyBlobUploadStatus(blobInfo.correlationId, isSuccess, statusCode, statusDescription); } // Create a client device from the connection string and upload the local file to blob storage. const deviceClient = Client.fromConnectionString(deviceConnectionString, Protocol); uploadToBlob(localFilePath, deviceClient) .catch((err) => { console.log(err); }) .finally(() => { process.exit(); });
保存并关闭 FileUpload.js 文件。
将图像文件复制到
fileupload
文件夹,并为其指定名称,例如myimage.png
。为设备连接字符串添加环境变量并添加要上传的文件的路径。 在 IoT 中心注册设备时,你收到了设备连接字符串。
对于 Windows:
set DEVICE_CONNECTION_STRING={your device connection string} set PATH_TO_FILE={your image filepath}
对于 Linux/Bash:
export DEVICE_CONNECTION_STRING="{your device connection string}" export PATH_TO_FILE="{your image filepath}"
获取 IoT 中心连接字符串
在本文中,你将创建一项后端服务,用于从你创建的 IoT 中心接收文件上传通知消息。 若要接收文件上传通知消息,服务需要服务连接权限。 默认情况下,每个 IoT 中心都使用名为“服务”的共享访问策略创建,该策略会授予此权限。
若要获取 service策略的 IoT 中心连接字符串,请执行以下步骤:
在 Azure 门户中,选择“资源组”。 选择中心所在的资源组,然后从资源列表中选择中心。
在 IoT 中心的左侧窗格上,选择“共享访问策略”。
在策略列表中,选择“service”策略。
复制“主连接字符串”并保存该值。
有关 IoT 中心共享访问策略和权限的详细信息,请参阅访问控制和权限。
接收文件上传通知
本部分中的操作将会创建一个 Node.js 控制台应用,用于接收来自 IoT 中心的文件上传通知消息。
创建名为
fileuploadnotification
的空文件夹。 在fileuploadnotification
文件夹的命令提示符处,使用以下命令创建 package.json 文件。 接受所有默认值:npm init
在
fileuploadnotification
文件夹中的命令提示符下,运行以下命令安装 azure-iothub SDK 包:npm install azure-iothub --save
使用文本编辑器在
fileuploadnotification
文件夹中创建 FileUploadNotification.js 文件。在 FileUploadNotification.js 文件的开头添加以下
require
语句:'use strict'; const Client = require('azure-iothub').Client;
从环境中读取 IoT 中心的连接字符串:
const connectionString = process.env.IOT_HUB_CONNECTION_STRING;
添加以下代码,从连接字符串创建服务客户端:
const serviceClient = Client.fromConnectionString(connectionString);
打开客户端,并使用 getFileNotificationReceiver 函数接收状态更新。
serviceClient.open(function (err) { if (err) { console.error('Could not connect: ' + err.message); } else { console.log('Service client connected'); serviceClient.getFileNotificationReceiver(function receiveFileUploadNotification(err, receiver){ if (err) { console.error('error getting the file notification receiver: ' + err.toString()); } else { receiver.on('message', function (msg) { console.log('File upload from device:') console.log(msg.getData().toString('utf-8')); }); } }); } });
注意
如果要在侦听文件上传通知时接收断开连接通知,则需要通过使用
receiver.on
来注册'error'
。 若要继续接收文件上传通知,则需要通过使用serviceClient.open
方法来重新连接到 IoT 中心。保存并关闭 FileUploadNotification.js 文件。
为 IoT 中心连接字符串添加环境变量。 你先前在获取 IoT 中心连接字符串中复制了此字符串。
对于 Windows:
set IOT_HUB_CONNECTION_STRING={your iot hub connection string}
对于 Linux/Bash:
export IOT_HUB_CONNECTION_STRING="{your iot hub connection string}"
运行应用程序
现在已准备就绪,可以运行应用程序了。
在 fileuploadnotification
文件夹中的命令提示符下运行以下命令:
node FileUploadNotification.js
在 fileupload
文件夹中的命令提示符下运行以下命令:
node FileUpload.js
以下输出来自上传完成后的 FileUpload 应用:
uploadStreamToBlockBlob success
notifyBlobUploadStatus success
以下示例输出来自上传完成后的 FileUploadNotification 应用:
Service client connected
File upload from device:
{"deviceId":"myDeviceId","blobUri":"https://{your storage account name}.blob.core.chinacloudapi.cn/device-upload-container/myDeviceId/image.png","blobName":"myDeviceId/image.png","lastUpdatedTime":"2021-07-23T23:27:06+00:00","blobSizeInBytes":26214,"enqueuedTimeUtc":"2021-07-23T23:27:07.2580791Z"}
验证文件上传
可以使用门户查看所配置的存储容器中上传的文件:
在 Azure 门户中导航到存储帐户。
在存储帐户的左侧窗格中,选择“容器”。
选择已将文件上传到其中的容器。
选择与设备同名的文件夹。
选择已将文件上传到其中的 Blob。 在本文中,它是与你的文件同名的 Blob。
在打开的页面上查看 Blob 属性。 可以选择“下载”,以将该文件下载到本地并查看其内容。
后续步骤
在本文中,你已学习了如何使用 IoT 中心的文件上传功能来简化从设备进行的文件上传。 可以继续通过以下文章了解此功能: