Upload files from a device to the cloud with Azure IoT Hub
This article demonstrates how to:
- Use file upload capabilities of IoT Hub to upload a file to Azure Blob Storage, using an Azure IoT device and service SDKs.
- Notify IoT Hub that the file was successfully uploaded and create a backend service to receive file upload notifications from IoT Hub, using the Azure IoT service SDKs.
In some scenarios, you can't easily map the data your devices send into the relatively small device-to-cloud messages that IoT Hub accepts. The file upload capabilities in IoT Hub enable you to move large or complex data to the cloud. For example:
- Videos
- Large files that contain images
- Vibration data sampled at high frequency
- Some form of preprocessed data
These files are typically batch processed in the cloud, using tools such as Azure Data Factory or the Hadoop stack. When you need to upload files from a device, you can still use the security and reliability of IoT Hub. This article shows you how.
This article is meant to complement runnable SDK samples that are referenced from within this article.
For more information, see:
Important
File upload functionality on devices that use X.509 certificate authority (CA) authentication is in public preview, and preview mode must be enabled. It is generally available on devices that use X.509 thumbprint authentication or X.509 certificate attestation with Azure Device Provisioning Service. To learn more about X.509 authentication with IoT Hub, see Supported X.509 certificates.
Prerequisites
An IoT hub. Some SDK calls require the IoT Hub primary connection string, so make a note of the connection string.
A registered device. Some SDK calls require the device primary connection string, so make a note of the connection string.
IoT Hub Service Connect permission - To receive file upload notification messages, your backend service needs the Service Connect permission. By default, every IoT Hub is created with a shared access policy named service that grants this permission. For more information, see Connect to an IoT hub.
Configure file upload in your IoT hub by linking an Azure Storage account and Azure Blob Storage container. You can configure these using the Azure portal, Azure CLI, or Azure PowerShell.
Overview
This how-to contains two sections:
- Upload a file from a device application
- Receive file upload notification in a backend application
Upload a file from a device application
This section describes how to upload a file from a device to an IoT hub using the DeviceClient class in the Azure IoT SDK for .NET.
Follow this procedure to upload a file from a device to IoT hub:
- Connect to IoT hub
- Get a SAS URI from IoT hub
- Upload the file to Azure storage
- Notify IoT hub of the file upload status
Connect a device to IoT Hub
A device app can authenticate with IoT Hub using the following methods:
- X.509 certificate
- Shared access key
Authenticate using an X.509 certificate
To connect a device to IoT Hub using an X.509 certificate:
Use DeviceAuthenticationWithX509Certificate to create an object that contains device and certificate information.
DeviceAuthenticationWithX509Certificate
is passed as the second parameter toDeviceClient.Create
(step 2).Use DeviceClient.Create to connect the device to IoT Hub using an X.509 certificate.
In this example, device and certificate information is populated in the auth
DeviceAuthenticationWithX509Certificate
object that is passed to DeviceClient.Create
.
This example shows certificate input parameter values as local variables for clarity. In a production system, store sensitive input parameters in environment variables or another more secure storage location. For example, use Environment.GetEnvironmentVariable("HOSTNAME")
to read the host name environment variable.
RootCertPath = "~/certificates/certs/sensor-thl-001-device.cert.pem";
Intermediate1CertPath = "~/certificates/certs/sensor-thl-001-device.intermediate1.cert.pem";
Intermediate2CertPath = "~/certificates/certs/sensor-thl-001-device.intermediate2.cert.pem";
DevicePfxPath = "~/certificates/certs/sensor-thl-001-device.cert.pfx";
DevicePfxPassword = "1234";
DeviceName = "MyDevice";
HostName = "xxxxx.azure-devices.net";
var chainCerts = new X509Certificate2Collection();
chainCerts.Add(new X509Certificate2(RootCertPath));
chainCerts.Add(new X509Certificate2(Intermediate1CertPath));
chainCerts.Add(new X509Certificate2(Intermediate2CertPath));
using var deviceCert = new X509Certificate2(DevicePfxPath, DevicePfxPassword);
using var auth = new DeviceAuthenticationWithX509Certificate(DeviceName, deviceCert, chainCerts);
using var deviceClient = DeviceClient.Create(
HostName,
auth,
TransportType.Amqp);
For more information about certificate authentication, see:
- Authenticate identities with X.509 certificates
- Tutorial: Create and upload certificates for testing
Code samples
For working samples of device X.509 certificate authentication, see:
- Connect with X.509 certificate
- DeviceClientX509AuthenticationE2ETests
- Guided project - Provision IoT devices securely and at scale with IoT Hub Device Provisioning Service
Authenticate using a shared access key
Call CreateFromConnectionString to connect to the device. Pass the device primary connection string.
AMQP
is the default transport protocol.
static string connectionString = "{device primary connection string}";
deviceClient = DeviceClient.CreateFromConnectionString(connectionString);
Get a SAS URI from IoT hub
Call GetFileUploadSasUriAsync to get file upload details. The SAS URI is used in the next step to upload a file from a device to Blob Storage.
const string filePath = "TestPayload.txt";
using var fileStreamSource = new FileStream(filePath, FileMode.Open);
var fileName = Path.GetFileName(fileStreamSource.Name);
var fileUploadSasUriRequest = new FileUploadSasUriRequest
{
BlobName = fileName
};
FileUploadSasUriResponse sasUri = await _deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest, System.Threading.CancellationToken cancellationToken = default);
Uri uploadUri = sasUri.GetBlobUri();
Upload a file to Azure storage
To upload a file to Azure storage:
Create a blockBlobClient object, passing a file upload URI.
Use the UploadAsync method to upload a file to Blob Storage, passing the SAS URI. You can optionally add Blob upload options and cancellation token parameters.
The Azure Blob client always uses HTTPS as the protocol to upload the file to Azure Storage.
In this example, BlockBlobClient
is passed the SAS URI to create an Azure Storage block Blob client and uploads the file:
var blockBlobClient = new BlockBlobClient(uploadUri);
await blockBlobClient.UploadAsync(fileStreamSource, null, null);
Notify IoT hub of the file upload status
Use CompleteFileUploadAsync to notify IoT hub that the device client completed the upload, passing a FileUploadCompletionNotification object. The IsSuccess
flag indicates whether or not the upload was successful. After being notified, IoT hub will release resources associated with the upload (the SAS URI).
If file upload notifications are enabled, IoT hub sends a file upload notification message to backend services that are configured for file upload notification.
var successfulFileUploadCompletionNotification = new FileUploadCompletionNotification
{
// Mandatory. Must be the same value as the correlation id returned in the sas uri response
CorrelationId = sasUri.CorrelationId,
// Mandatory. Will be present when service client receives this file upload notification
IsSuccess = true,
// Optional, user defined status code. Will be present when service client receives this file upload notification
StatusCode = 200,
// Optional, user-defined status description. Will be present when service client receives this file upload notification
StatusDescription = "Success"
};
await _deviceClient.CompleteFileUploadAsync(successfulFileUploadCompletionNotification);
SDK file upload sample
The SDK includes this file upload sample.
Receive a file upload notification in a backend application
You can create a backend service to receive file upload notification messages from IoT hub.
The ServiceClient class contains methods that services can use to receive file upload notifications.
Add service NuGet Package
Backend service applications require the Microsoft.Azure.Devices NuGet package.
Connect to IoT hub
You can connect a backend service to IoT Hub using the following methods:
- Shared access policy
- Microsoft Entra
Important
This article includes steps to connect to a service using a shared access signature. This authentication method is convenient for testing and evaluation, but authenticating to a service with Microsoft Entra ID or managed identities is a more secure approach. To learn more, see Security best practices > Cloud security.
Connect using a shared access policy
Connect a backend application to a device using CreateFromConnectionString. Your application needs service connect permission. Supply this shared access policy connection string as a parameter to fromConnectionString
. For more information about shared access policies, see Control access to IoT Hub with shared access signatures.
For example:
using Microsoft.Azure.Devices;
static ServiceClient serviceClient;
static string connectionString = "{Shared access policy connection string}";
serviceClient = ServiceClient.CreateFromConnectionString(connectionString);
Connect using Microsoft Entra
A backend app that uses Microsoft Entra must successfully authenticate and obtain a security token credential before connecting to IoT Hub. This token is passed to a IoT Hub connection method. For general information about setting up and using Microsoft Entra for IoT Hub, see Control access to IoT Hub by using Microsoft Entra ID.
Configure Microsoft Entra app
You must set up a Microsoft Entra app that is configured for your preferred authentication credential. The app contains parameters such as client secret that are used by the backend application to authenticate. The available app authentication configurations are:
- Client secret
- Certificate
- Federated identity credential
Microsoft Entra apps may require specific role permissions depending on operations being performed. For example, IoT Hub Twin Contributor is required to enable read and write access to a IoT Hub device and module twins. For more information, see Manage access to IoT Hub by using Azure RBAC role assignment.
For more information about setting up a Microsoft Entra app, see Quickstart: Register an application with the Microsoft identity platform.
Authenticate using DefaultAzureCredential
The easiest way to use Microsoft Entra to authenticate a backend application is to use DefaultAzureCredential, but it's recommended to use a different method in a production environment including a specific TokenCredential
or pared-down ChainedTokenCredential
. For simplicity, this section describes authentication using DefaultAzureCredential
and Client secret. For more information about the pros and cons of using DefaultAzureCredential
, see Usage guidance for DefaultAzureCredential.
DefaultAzureCredential
supports different authentication mechanisms and determines the appropriate credential type based on the environment it's executing in. It attempts to use multiple credential types in an order until it finds a working credential.
Microsoft Entra requires these NuGet packages and corresponding using
statements:
- Azure.Core
- Azure.Identity
using Azure.Core;
using Azure.Identity;
In this example, Microsoft Entra app registration client secret, client ID, and tenant ID are added to environment variables. These environment variables are used by DefaultAzureCredential
to authenticate the application. The result of a successful Microsoft Entra authentication is a security token credential that is passed to an IoT Hub connection method.
string clientSecretValue = "xxxxxxxxxxxxxxx";
string clientID = "xxxxxxxxxxxxxx";
string tenantID = "xxxxxxxxxxxxx";
Environment.SetEnvironmentVariable("AZURE_CLIENT_SECRET", clientSecretValue);
Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", clientID);
Environment.SetEnvironmentVariable("AZURE_TENANT_ID", tenantID);
TokenCredential tokenCredential = new DefaultAzureCredential();
The resulting TokenCredential can then be passed to a connect to IoT Hub method for any SDK client that accepts Microsoft Entra credentials:
In this example, the TokenCredential
is passed to ServiceClient.Create
to create a ServiceClient connection object.
string hostname = "xxxxxxxxxx.azure-devices.net";
using var serviceClient = ServiceClient.Create(hostname, tokenCredential, TransportType.Amqp);
In this example, the TokenCredential
is passed to RegistryManager.Create
to create a RegistryManager object.
string hostname = "xxxxxxxxxx.azure-devices.net";
registryManager = RegistryManager.Create(hostname, tokenCredential);
Code sample
For a working sample of Microsoft Entra service authentication, see Role based authentication sample.
Receive file upload notification
To receive file upload notification:
- Create a CancellationToken.
- Call GetFileNotificationReceiver to create a notification receiver.
- Use a loop with ReceiveAsync to wait for the file upload notification.
For example:
// Define the cancellation token
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
// Create a notification receiver
var notificationReceiver = serviceClient.GetFileNotificationReceiver();
Console.WriteLine("\nReceiving file upload notification from service");
// Check for file upload notifications
while (true)
{
var fileUploadNotification = await notificationReceiver.ReceiveAsync(token);
if (fileUploadNotification == null) continue;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Received file upload notification: {0}",
string.Join(", ", fileUploadNotification.BlobName));
Console.ResetColor();
await notificationReceiver.CompleteAsync(fileUploadNotification);
}
SDK file upload receiver sample
The SDK includes this file upload receiver sample.
Overview
This how-to contains two sections:
- Upload a file from a device application
- Receive file upload notification in a backend application
Upload a file from a device application
This section describes how to upload a file from a device to an IoT hub using the DeviceClient class from the Azure IoT SDK for Java.
Follow this procedure to upload a file from a device to IoT hub:
- Connect the device to IoT Hub
- Get a SAS URI from IoT hub
- Upload the file to Azure Storage
- Send file upload status notification to IoT hub
Connect a device to IoT Hub
A device app can authenticate with IoT Hub using the following methods:
- X.509 certificate
- Shared access key
Authenticate using an X.509 certificate
To connect a device to IoT Hub using an X.509 certificate:
- Build the SSLContext object using buildSSLContext.
- Add the
SSLContext
information to a ClientOptions object. - Call DeviceClient using the
ClientOptions
information to create the device-to-IoT Hub connection.
This example shows certificate input parameter values as local variables for clarity. In a production system, store sensitive input parameters in environment variables or another more secure storage location. For example, use Environment.GetEnvironmentVariable("PUBLICKEY")
to read a public key certificate string environment variable.
private static final String publicKeyCertificateString =
"-----BEGIN CERTIFICATE-----\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"-----END CERTIFICATE-----\n";
//PEM encoded representation of the private key
private static final String privateKeyString =
"-----BEGIN EC PRIVATE KEY-----\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"-----END EC PRIVATE KEY-----\n";
SSLContext sslContext = SSLContextBuilder.buildSSLContext(publicKeyCertificateString, privateKeyString);
ClientOptions clientOptions = ClientOptions.builder().sslContext(sslContext).build();
DeviceClient client = new DeviceClient(connString, protocol, clientOptions);
For more information about certificate authentication, see:
- Authenticate identities with X.509 certificates
- Tutorial: Create and upload certificates for testing
Code samples
For working samples of device X.509 certificate authentication, see:
Authenticate using a shared access key
File upload operations always use HTTPS, but DeviceClient can define the IotHubClientProtocol for other services like telemetry, device method, and device twin.
IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
Instantiate the DeviceClient
to connect to the device using the device primary connection string.
String connString = "{IoT hub connection string}";
DeviceClient client = new DeviceClient(connString, protocol);
Get a SAS URI from IoT hub
Call getFileUploadSasUri to obtain a FileUploadSasUriResponse object.
FileUploadSasUriResponse
includes these methods and return values. The return values can be passed to file upload methods.
Method | Return value |
---|---|
getCorrelationId() |
Correlation ID |
getContainerName() |
Container name |
getBlobName() |
Blob name |
getBlobUri() |
Blob URI |
For example:
FileUploadSasUriResponse sasUriResponse = client.getFileUploadSasUri(new FileUploadSasUriRequest(file.getName()));
System.out.println("Successfully got SAS URI from IoT hub");
System.out.println("Correlation Id: " + sasUriResponse.getCorrelationId());
System.out.println("Container name: " + sasUriResponse.getContainerName());
System.out.println("Blob name: " + sasUriResponse.getBlobName());
System.out.println("Blob Uri: " + sasUriResponse.getBlobUri());
Upload the file to Azure Storage
Pass the blob URI endpoint to BlobClientBuilder.buildclient to create the BlobClient object.
BlobClient blobClient =
new BlobClientBuilder()
.endpoint(sasUriResponse.getBlobUri().toString())
.buildClient();
Call uploadFromFile to upload the file to Blob Storage.
String fullFileName = "Path of the file to upload";
blobClient.uploadFromFile(fullFileName);
Send file upload status notification to IoT hub
Send an upload status notification to IoT hub after a file upload attempt.
Create a FileUploadCompletionNotification object. Pass the correlationId
and isSuccess
file upload success status. Pass an isSuccess
true
value when file upload was successful, false
when not.
FileUploadCompletionNotification
must be called even when the file upload fails. IoT hub has a fixed number of SAS URI allowed to be active at any given time. Once you're done with the file upload, you should free your SAS URI so that other SAS URI can be generated. If a SAS URI isn't freed through this API, then it frees itself eventually based on how long SAS URIs are configured to live on an IoT hub.
This example passes a successful status.
FileUploadCompletionNotification completionNotification = new FileUploadCompletionNotification(sasUriResponse.getCorrelationId(), true);
client.completeFileUpload(completionNotification);
Close the client
Free the client
resources.
client.closeNow();
Create a backend application
This section describes how to receive a file upload notification in a backend application.
The ServiceClient class contains methods that services can use to receive file upload notifications.
Add import statements
Add these import statements to use the Azure IoT Java SDK and exception handler.
import com.microsoft.azure.sdk.iot.service.*;
import java.io.IOException;
import java.net.URISyntaxException;
Connect to the IoT Hub
You can connect a backend service to IoT Hub using the following methods:
- Shared access policy
- Microsoft Entra
Important
This article includes steps to connect to a service using a shared access signature. This authentication method is convenient for testing and evaluation, but authenticating to a service with Microsoft Entra ID or managed identities is a more secure approach. To learn more, see Security best practices > Cloud security.
Connect using a shared access policy
Define the connection protocol
Use IotHubServiceClientProtocol to define the application-layer protocol used by the service client to communicate with an IoT Hub.
IotHubServiceClientProtocol
only accepts the AMQPS
or AMQPS_WS
enum.
private static final IotHubServiceClientProtocol protocol =
IotHubServiceClientProtocol.AMQPS;
Create the ServiceClient object
Create the ServiceClient object, supplying the Iot Hub connection string and protocol.
To upload a file on a device to IoT Hub, your service needs the service connect permission. By default, every IoT Hub is created with a shared access policy named service that grants this permission.
As a parameter to the ServiceClient
constructor, supply the service shared access policy. For more information about shared access policies, see Control access to IoT Hub with shared access signatures.
String iotHubConnectionString = "HostName=xxxxx.azure-devices.net;SharedAccessKeyName=service;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxx";
private static final ServiceClient serviceClient (iotHubConnectionString, protocol);
Open the connection between application and IoT Hub
Open the AMQP sender connection. This method creates the connection between the application and IoT Hub.
serviceClient.open();
Connect using Microsoft Entra
A backend app that uses Microsoft Entra must successfully authenticate and obtain a security token credential before connecting to IoT Hub. This token is passed to a IoT Hub connection method. For general information about setting up and using Microsoft Entra for IoT Hub, see Control access to IoT Hub by using Microsoft Entra ID.
For an overview of Java SDK authentication, see Azure authentication with Java and Azure Identity.
For simplicity, this section focuses on describing authentication using client secret.
Configure Microsoft Entra app
You must set up a Microsoft Entra app that is configured for your preferred authentication credential. The app contains parameters such as client secret that are used by the backend application to authenticate. The available app authentication configurations are:
- Client secret
- Certificate
- Federated identity credential
Microsoft Entra apps may require specific role permissions depending on operations being performed. For example, IoT Hub Twin Contributor is required to enable read and write access to a IoT Hub device and module twins. For more information, see Manage access to IoT Hub by using Azure RBAC role assignment.
For more information about setting up a Microsoft Entra app, see Quickstart: Register an application with the Microsoft identity platform.
Authenticate using DefaultAzureCredential
The easiest way to use Microsoft Entra to authenticate a backend application is to use DefaultAzureCredential, but it's recommended to use a different method in a production environment including a specific TokenCredential
or pared-down ChainedTokenCredential
.
For more information about the pros and cons of using DefaultAzureCredential
, see
Credential chains in the Azure Identity client library for Java.
DefaultAzureCredential supports different authentication mechanisms and determines the appropriate credential type based on the environment it's executing in. It attempts to use multiple credential types in an order until it finds a working credential.
You can authenticate Microsoft Entra app credentials using DefaultAzureCredentialBuilder. Save connection parameters such as client secret tenantID, clientID, and client secret values as environmental variables. Once the TokenCredential
is created, pass it to ServiceClient or other builder as the 'credential' parameter.
In this example, DefaultAzureCredentialBuilder
attempts to authenticate a connection from the list described in DefaultAzureCredential. The result of a successful Microsoft Entra authentication is a security token credential that is passed to a constructor such as ServiceClient.
TokenCredential defaultAzureCredential = new DefaultAzureCredentialBuilder().build();
Authenticate using ClientSecretCredentialBuilder
You can use ClientSecretCredentialBuilder to create a credential using client secret information. If successful, this method returns a TokenCredential that can be passed to ServiceClient or other builder as the 'credential' parameter.
In this example, Microsoft Entra app registration client secret, client ID, and tenant ID values have been added to environment variables. These environment variables are used by ClientSecretCredentialBuilder
to build the credential.
string clientSecretValue = System.getenv("AZURE_CLIENT_SECRET");
string clientID = System.getenv("AZURE_CLIENT_ID");
string tenantID = System.getenv("AZURE_TENANT_ID");
TokenCredential credential =
new ClientSecretCredentialBuilder()
.tenantId(tenantID)
.clientId(clientID)
.clientSecret(clientSecretValue)
.build();
Other authentication classes
The Java SDK also includes these classes that authenticate a backend app with Microsoft Entra:
- AuthorizationCodeCredential
- AzureCliCredential
- AzureDeveloperCliCredential
- AzurePipelinesCredential
- ChainedTokenCredential
- ClientAssertionCredential
- ClientCertificateCredential
- DeviceCodeCredential
- EnvironmentCredential
- InteractiveBrowserCredential
- ManagedIdentityCredential
- OnBehalfOfCredential
Code samples
For working samples of Microsoft Entra service authentication, see Role based authentication sample.
Check for file upload status
To check for file upload status:
- Create a getFileUploadNotificationReceiver object.
- Use open to connect to IoT hub.
- Call receive to check for the file upload status. This method returns a fileUploadNotification object. If an upload notice is received, you can view upload status fields using fileUploadNotification methods.
For example:
FileUploadNotificationReceiver receiver = serviceClient.getFileUploadNotificationReceiver();
receiver.open();
FileUploadNotification fileUploadNotification = receiver.receive(2000);
if (fileUploadNotification != null)
{
System.out.println("File Upload notification received");
System.out.println("Device Id : " + fileUploadNotification.getDeviceId());
System.out.println("Blob Uri: " + fileUploadNotification.getBlobUri());
System.out.println("Blob Name: " + fileUploadNotification.getBlobName());
System.out.println("Last Updated : " + fileUploadNotification.getLastUpdatedTimeDate());
System.out.println("Blob Size (Bytes): " + fileUploadNotification.getBlobSizeInBytes());
System.out.println("Enqueued Time: " + fileUploadNotification.getEnqueuedTimeUtcDate());
}
else
{
System.out.println("No file upload notification");
}
// Close the receiver object
receiver.close();
SDK file upload samples
There are two Java file upload samples.
Install packages
The azure-iot-device library must be installed before calling any related code.
pip install azure-iot-device
The azure.storage.blob package is used to perform the file upload.
pip install azure.storage.blob
Upload file from a device application
This section describes how to upload a file from a device to an IoT hub using the IoTHubDeviceClient class from the Azure IoT SDK for Python.
Import libraries
import os
from azure.iot.device import IoTHubDeviceClient
from azure.core.exceptions import AzureError
from azure.storage.blob import BlobClient
Connect a device to IoT Hub
A device app can authenticate with IoT Hub using the following methods:
- X.509 certificate
- Shared access key
Authenticate using an X.509 certificate
To connect a device to IoT Hub using an X.509 certificate:
- Use create_from_x509_certificate to add the X.509 certificate parameters
- Call connect to connect the device client
This example shows certificate input parameter values as local variables for clarity. In a production system, store sensitive input parameters in environment variables or another more secure storage location. For example, use os.getenv("HOSTNAME")
to read the host name environment variable.
# The Azure IoT hub name
hostname = "xxxxx.azure-devices.net"
# The device that has been created on the portal using X509 CA signing or self-signing capabilities
device_id = "MyDevice"
# The X.509 certificate file name
cert_file = "~/certificates/certs/sensor-thl-001-device.cert.pfx"
key_file = "~/certificates/certs/sensor-thl-001-device.cert.key"
# The optional certificate pass phrase
pass_phrase = "1234"
x509 = X509(
cert_file,
key_file,
pass_phrase,
)
# The client object is used to interact with your Azure IoT hub.
device_client = IoTHubDeviceClient.create_from_x509_certificate(
hostname=hostname, device_id=device_id, x509=x509
)
# Connect to IoT Hub
await device_client.connect()
For more information about certificate authentication, see:
- Authenticate identities with X.509 certificates
- Tutorial: Create and upload certificates for testing
Code samples
For working samples of device X.509 certificate authentication, see the examples whose file names end in x509 at Async hub scenarios.
Authenticate using a shared access key
To connect a device to IoT Hub:
- Call create_from_connection_string to add the device primary connection string.
- Call connect to connect the device client.
For example:
# Add your IoT hub primary connection string
CONNECTION_STRING = "{Device primary connection string}"
device_client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)
# Connect the client
device_client.connect()
Get Blob Storage information
Call get_storage_info_for_blob to get information from an IoT hub about a linked Azure Storage account. This information includes the hostname, container name, blob name, and a SAS token. The get_storage_info_for_blob
method also returns a correlation_id
, which is used in the notify_blob_upload_status
method. The correlation_id
is IoT Hub's way of marking which Blob you're working on.
# Get the storage info for the blob
PATH_TO_FILE = "{Full path to local file}"
blob_name = os.path.basename(PATH_TO_FILE)
blob_info = device_client.get_storage_info_for_blob(blob_name)
Upload a file into Blob Storage
To upload a file into Blob Storage:
- Use from_blob_url to create a BlobClient object from a blob URL.
- Call upload_blob to upload the file into the Blob Storage.
This example parses the blob_info
structure to create a URL that it uses to initialize an BlobClient. Then it calls upload_blob
to upload the file into Blob Storage.
try:
sas_url = "https://{}/{}/{}{}".format(
blob_info["hostName"],
blob_info["containerName"],
blob_info["blobName"],
blob_info["sasToken"]
)
print("\nUploading file: {} to Azure Storage as blob: {} in container {}\n".format(file_name, blob_info["blobName"], blob_info["containerName"]))
# Upload the specified file
with BlobClient.from_blob_url(sas_url) as blob_client:
with open(file_name, "rb") as f:
result = blob_client.upload_blob(f, overwrite=True)
return (True, result)
except FileNotFoundError as ex:
# catch file not found and add an HTTP status code to return in notification to IoT hub
ex.status_code = 404
return (False, ex)
except AzureError as ex:
# catch Azure errors that might result from the upload operation
return (False, ex)
Notify IoT hub of upload status
Use notify_blob_upload_status to notify IoT hub of the status of the Blob Storage operation. Pass the correlation_id
obtained by the get_storage_info_for_blob
method. The correlation_id
is used by IoT hub to notify any service that might be listening for a notification regarding the status of the file upload task.
This example notifies IoT hub of a successful file upload:
device_client.notify_blob_upload_status(storage_info["correlationId"], True, 200, "OK: {}".format(PATH_TO_FILE)
Shut down the device client
Shut down the client. Once this method is called, any attempt at further client calls result in a ClientError being raised.
device_client.shutdown()
SDK file upload samples
The SDK includes two file upload samples:
Overview
This article describes how to use the Azure IoT SDK for Node.js to create a device app to upload a file and backend service application receive file upload notification.
Create a device application
This section describes how to upload a file from a device to an IoT hub using the azure-iot-device package in the Azure IoT SDK for Node.js.
Install SDK packages
Run this command to install the azure-iot-device device SDK, the azure-iot-device-mqtt, and the @azure/storage-blob packages on your development machine:
npm install azure-iot-device azure-iot-device-mqtt @azure/storage-blob --save
The azure-iot-device package contains objects that interface with IoT devices.
Follow this procedure to upload a file from a device to IoT hub:
- Connect the device to IoT Hub
- Get a Blob shared access signature (SAS) token from IoT Hub
- Upload the file to Azure Storage
- Send file upload status notification to IoT hub
Create modules
Create Client, Protocol, errors, and path modules using the installed packages.
const Protocol = require('azure-iot-device-mqtt').Mqtt;
const errors = require('azure-iot-common').errors;
const path = require('path');
Connect a device to IoT Hub
A device app can authenticate with IoT Hub using the following methods:
- X.509 certificate
- Shared access key
Authenticate using an X.509 certificate
The X.509 certificate is attached to the device-to-IoT Hub connection transport.
To configure a device-to-IoT Hub connection using an X.509 certificate:
- Call fromConnectionString to add the device connection string and transport type. Add
x509=true
to the device connection string to indicate that a certificate is added toDeviceClientOptions
. For example:HostName=xxxxx.azure-devices.net;DeviceId=Device-1;SharedAccessKey=xxxxxxxxxxxxx;x509=true
. - Configure a JSON variable with certificate details and pass it to DeviceClientOptions.
- Call setOptions to add an X.509 certificate and key (and optionally, passphrase) to the client transport.
- Call open to open the connection from the device to IoT Hub.
This example shows certificate configuration information within a JSON variable. The certification configuration options
are passed to setOptions
and the connection is opened using open
.
var options = {
cert: myX509Certificate,
key: myX509Key,
passphrase: passphrase,
http: {
receivePolicy: {
interval: 10
}
}
}
client.setOptions(options, callback);
client.open(connectCallback);
For more information about certificate authentication, see:
Code sample
For a working sample of device X.509 certificate authentication, see Simple sample device X.509.
Authenticate using a shared access key
Choose a transport protocol
The Client
object supports these protocols:
Amqp
Http
- When usingHttp
, theClient
instance checks for messages from IoT Hub infrequently (a minimum of every 25 minutes).Mqtt
MqttWs
AmqpWs
Install needed transport protocols on your development machine.
For example, this command installs the Amqp
protocol:
npm install azure-iot-device-amqp --save
For more information about the differences between MQTT, AMQP, and HTTPS support, see Cloud-to-device communications guidance and Choose a communication protocol.
Create a client object
Create a Client
object using the installed package.
For example:
const Client = require('azure-iot-device').Client;
Create a protocol object
Create a Protocol
object using an installed transport package.
This example assigns the AMQP protocol:
const Protocol = require('azure-iot-device-amqp').Amqp;
Add the device connection string and transport protocol
Call fromConnectionString to supply device connection parameters:
- connStr - The device connection string.
- transportCtor - The transport protocol.
This example uses the Amqp
transport protocol:
const deviceConnectionString = "{IoT hub device connection string}"
const Protocol = require('azure-iot-device-mqtt').Amqp;
let client = Client.fromConnectionString(deviceConnectionString, Protocol);
Open the connection to IoT Hub
Use the open method to open connection between an IoT device and IoT Hub.
For example:
client.open(function(err) {
if (err) {
console.error('error connecting to hub: ' + err);
process.exit(1);
}
})
Get a SAS token from IoT hub
Use getBlobSharedAccessSignature to get the linked storage account SAS token from IoT hub.
For example:
// make sure you set these environment variables prior to running the sample.
const localFilePath = process.env.PATH_TO_FILE;
const storageBlobName = path.basename(localFilePath);
const blobInfo = await client.getBlobSharedAccessSignature(storageBlobName);
if (!blobInfo) {
throw new errors.ArgumentError('Invalid upload parameters');
}
Upload the file to IoT hub
To upload a file from a device to IoT hub:
- Create a stream pipeline
- Construct the blob URL
- Create a BlockBlobClient for file upload to Blob Storage
- Call uploadFile to upload the file to Blob Storage
- Call notifyBlobUploadStatus to notify IoT hub that the upload succeeded or failed
For example:
// Open the pipeline
const pipeline = newPipeline(new AnonymousCredential(), {
retryOptions: { maxTries: 4 },
telemetry: { value: 'HighLevelSample V1.0.0' }, // Customized telemetry string
keepAliveOptions: { enable: false }
});
// Construct the blob URL
const { hostName, containerName, blobName, sasToken } = blobInfo;
const blobUrl = `https://${hostName}/${containerName}/${blobName}${sasToken}`;
// Create the BlockBlobClient for file upload to Blob Storage
const blobClient = new BlockBlobClient(blobUrl, pipeline);
// Setup blank status notification arguments to be filled in on success/failure
let isSuccess;
let statusCode;
let statusDescription;
const uploadStatus = await blobClient.uploadFile(localFilePath);
console.log('uploadStreamToBlockBlob success');
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);
}
// Send file upload status notification to IoT hub
await client.notifyBlobUploadStatus(blobInfo.correlationId, isSuccess, statusCode, statusDescription);
Upload the local file to blob storage
You can upload a local file to blob storage from a computer
const deviceClient = Client.fromConnectionString(deviceConnectionString, Protocol);
uploadToBlob(localFilePath, deviceClient)
.catch((err) => {
console.log(err);
})
.finally(() => {
process.exit();
});
SDK file upload sample
The SDK includes an upload to blob advanced sample.
Create a backend application
This section describes how to receive file upload notifications in a backend application.
The ServiceClient class contains methods that services can use to receive file upload notifications.
Install service SDK package
Run this command to install azure-iothub on your development machine:
npm install azure-iothub --save
Connect to IoT hub
You can connect a backend service to IoT Hub using the following methods:
- Shared access policy
- Microsoft Entra
Important
This article includes steps to connect to a service using a shared access signature. This authentication method is convenient for testing and evaluation, but authenticating to a service with Microsoft Entra ID or managed identities is a more secure approach. To learn more, see Security best practices > Cloud security.
Connect using a shared access policy
Use fromConnectionString to connect to IoT hub.
To upload a file from a device, your service needs the service connect permission. By default, every IoT Hub is created with a shared access policy named service that grants this permission.
As a parameter to CreateFromConnectionString
, supply the service shared access policy connection string. For more information about shared access policies, see Control access to IoT Hub with shared access signatures.
var Client = require('azure-iothub').Client;
var connectionString = '{IoT hub shared access policy connection string}';
var client = Client.fromConnectionString(connectionString);
Connect using Microsoft Entra
A backend app that uses Microsoft Entra must successfully authenticate and obtain a security token credential before connecting to IoT Hub. This token is passed to a IoT Hub connection method. For general information about setting up and using Microsoft Entra for IoT Hub, see Control access to IoT Hub by using Microsoft Entra ID.
For an overview of Node.js SDK authentication, see:
Configure Microsoft Entra app
You must set up a Microsoft Entra app that is configured for your preferred authentication credential. The app contains parameters such as client secret that are used by the backend application to authenticate. The available app authentication configurations are:
- Client secret
- Certificate
- Federated identity credential
Microsoft Entra apps may require specific role permissions depending on operations being performed. For example, IoT Hub Twin Contributor is required to enable read and write access to a IoT Hub device and module twins. For more information, see Manage access to IoT Hub by using Azure RBAC role assignment.
For more information about setting up a Microsoft Entra app, see Quickstart: Register an application with the Microsoft identity platform.
Authenticate using DefaultAzureCredential
The easiest way to use Microsoft Entra to authenticate a backend application is to use DefaultAzureCredential, but it's recommended to use a different method in a production environment including a specific TokenCredential
or pared-down ChainedTokenCredential
. For simplicity, this section describes authentication using DefaultAzureCredential
and Client secret.
For more information about the pros and cons of using DefaultAzureCredential
, see
Credential chains in the Azure Identity client library for JavaScript
DefaultAzureCredential supports different authentication mechanisms and determines the appropriate credential type based on the environment it's executing in. It attempts to use multiple credential types in an order until it finds a working credential.
Microsoft Entra requires this package:
npm install --save @azure/identity
In this example, Microsoft Entra app registration client secret, client ID, and tenant ID have been added to environment variables. These environment variables are used by DefaultAzureCredential
to authenticate the application. The result of a successful Microsoft Entra authentication is a security token credential that is passed to an IoT Hub connection method.
import { DefaultAzureCredential } from "@azure/identity";
// Azure SDK clients accept the credential as a parameter
const credential = new DefaultAzureCredential();
The resulting credential token can then be passed to fromTokenCredential to connect to IoT Hub for any SDK client that accepts Microsoft Entra credentials:
fromTokenCredential
requires two parameters:
- The Azure service URL - The Azure service URL should be in the format
{Your Entra domain URL}.azure-devices.net
without ahttps://
prefix. For example,MyAzureDomain.azure-devices.net
. - The Azure credential token
In this example, the Azure credential is obtained using DefaultAzureCredential
. The Azure domain URL and credential are then supplied to Registry.fromTokenCredential
to create the connection to IoT Hub.
const { DefaultAzureCredential } = require("@azure/identity");
let Registry = require('azure-iothub').Registry;
// Define the client secret values
clientSecretValue = 'xxxxxxxxxxxxxxx'
clientID = 'xxxxxxxxxxxxxx'
tenantID = 'xxxxxxxxxxxxx'
// Set environment variables
process.env['AZURE_CLIENT_SECRET'] = clientSecretValue;
process.env['AZURE_CLIENT_ID'] = clientID;
process.env['AZURE_TENANT_ID'] = tenantID;
// Acquire a credential object
const credential = new DefaultAzureCredential()
// Create an instance of the IoTHub registry
hostName = 'MyAzureDomain.azure-devices.net';
let registry = Registry.fromTokenCredential(hostName,credential);
Code samples
For working samples of Microsoft Entra service authentication, see Azure identity examples.
Create a file upload notification callback receiver
To create a file upload notification callback receiver:
- Call getFileNotificationReceiver. Supply the name of a file upload callback method that is called when notification messages are received.
- Process file upload notifications in the callback method.
This example sets up a receiveFileUploadNotification
notification callback receiver. The receiver interprets the file upload status information and prints a status message to the console.
//Set up the receiveFileUploadNotification notification message callback receiver
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.complete(msg, function (err) {
if (err) {
console.error('Could not finish the upload: ' + err.message);
} else {
console.log('Upload complete');
}
});
});
}
SDK file upload notification sample
The SDK includes a file upload sample.