Azure IoT Hub를 사용하여 디바이스에서 클라우드로 파일 업로드(Node.js)

이 문서에서는 IoT Hub의 파일 업로드 기능이 Node.js를 사용하여 Azure Blob Storage에 파일을 업로드하는 방법을 보여줍니다.

디바이스에서 IoT 허브로 원격 분석 데이터 보내기 빠른 시작 및 IoT Hub를 사용하여 클라우드-디바이스 메시지 보내기 문서는 IoT Hub의 기본적인 디바이스-클라우드 및 클라우드-디바이스 메시징 기능을 보여 줍니다. IoT Hub로 메시지 라우팅 구성 자습서에서는 디바이스-클라우드 메시지를 Microsoft Azure Blob 스토리지에 안정적으로 저장하는 방법을 보여 줍니다. 그러나 일부 시나리오에서는 디바이스에서 전송하는 데이터를 IoT Hub에서 허용하는 비교적 작은 디바이스-클라우드 메시지에 쉽게 매핑할 수 없습니다. 예시:

  • 비디오
  • 이미지가 포함된 대형 파일
  • 자주 샘플링되는 진동 데이터
  • 특정 형태의 전처리된 데이터

이러한 파일은 일반적으로 Azure Data Factory 또는 Hadoop 스택과 같은 도구를 사용하여 클라우드에서 일괄 처리됩니다. 디바이스에서 파일을 업로드해야 할 때 IoT Hub의 보안 및 안정성을 여전히 사용할 수 있습니다. 이 문서에서 그 방법을 보여줍니다.

이 문서의 끝부분에서 다음 두 개의 Node.js 콘솔 앱을 실행합니다.

  • FileUpload.js - IoT 허브에서 제공하는 SAS URI를 사용하여 스토리지에 파일을 업로드합니다.

  • FileUploadNotification.js - IoT 허브에서 파일 업로드 알림을 받습니다.

참고 항목

IoT Hub는 Azure IoT 디바이스 SDK를 통해 다양한 디바이스 플랫폼 및 언어(C, Java, Python 및 JavaScript 포함)를 지원합니다. 디바이스를 Azure IoT Hub에 연결하는 방법에 자세한 내용은 Azure IoT 개발자 센터를 참조하세요.

Important

X.509 CA(인증 기관) 인증을 사용하는 디바이스의 파일 업로드 기능은 공개 미리 보기로 제공되고 있으며 미리 보기 모드를 사용하도록 설정해야 합니다. Azure Device Provisioning Service와 함께 X.509 지문 인증 또는 X.509 인증서 증명을 사용하는 디바이스에서 일반적으로 사용할 수 있습니다. IoT Hub를 사용하는 X.509 인증에 대해 자세히 알아보려면 지원되는 X.509 인증서를 참조하세요.

필수 조건

  • IoT 허브. CLI 또는 Azure Portal을 사용하여 만듭니다.

  • 등록된 디바이스. Azure Portal에 하나를 등록합니다.

  • Node.js 버전 10.0.x 이상. LTS 버전을 사용하는 것이 좋습니다. nodejs.org에서 Node.js를 다운로드할 수 있습니다.

  • 8883 포트는 방화벽에서 열려 있어야 합니다. 이 문서의 디바이스 샘플은 포트 8883을 통해 통신하는 MQTT 프로토콜을 사용합니다. 이 포트는 일부 회사 및 교육용 네트워크 환경에서 차단될 수 있습니다. 이 문제를 해결하는 자세한 내용과 방법은 IoT Hub에 연결(MQTT)을 참조하세요.

Azure Storage 계정을 IoT Hub에 연결

디바이스에서 파일을 업로드하려면 IoT 허브와 연결된 Azure Storage 계정 및 Azure Blob Storage 컨테이너가 있어야 합니다. 스토리지 계정 및 컨테이너를 IoT 허브와 연결하면 IoT 허브가 디바이스에서 요청될 때 SAS URI의 요소를 제공할 수 있습니다. 그런 다음, 디바이스는 이러한 요소를 사용하여 Azure Storage를 인증하고 Blob 컨테이너에 파일을 업로드하는 데 사용하는 SAS URI를 생성할 수 있습니다.

Azure Storage 계정을 IoT 허브와 연결하려면 다음을 수행합니다.

  1. 허브 설정 아래에서 사용자 IoT 허브의 왼쪽에 있는 파일 업로드를 선택합니다.

    포털에서 선택한 파일 업로드 설정을 보여 주는 화면 캡처.

  2. 파일 업로드 창에서 Azure Storage 컨테이너를 선택합니다. 이 문서에서는 스토리지 계정과 IoT Hub를 동일한 지역에 배치하는 것이 좋습니다.

    • 사용하려는 스토리지 계정이 이미 있는 경우 목록에서 선택합니다.

    • 새 스토리지 계정을 만들려면 +스토리지 계정을 선택합니다. 스토리지 계정에 대한 이름을 제공하고 위치가 IoT 허브와 동일한 지역으로 설정되었는지 확인한 다음, 확인을 선택합니다. 새 계정은 IoT 허브와 동일한 리소스 그룹에 만들어집니다. 배포가 완료되면 목록에서 스토리지 계정을 선택합니다.

    스토리지 계정을 선택하면 컨테이너 창이 열립니다.

  3. 컨테이너 창에서 Blob 컨테이너를 선택합니다.

    • 사용하려는 Blob 컨테이너가 이미 있는 경우 목록에서 선택하고 선택을 클릭합니다.

    • 새 Blob 컨테이너를 만들려면 + 컨테이너를 선택합니다. 새 컨테이너에 대한 이름을 제공합니다. 이 문서의 목적을 위해 다른 모든 필드를 기본값으로 그대로 둘 수 있습니다. 만들기를 실행합니다. 배포가 완료되면 목록에서 컨테이너를 선택하고 선택을 클릭합니다.

  4. 파일 업로드 창으로 다시 돌아가서 파일 알림이 켜짐으로 설정되었는지 확인합니다. 다른 모든 설정은 기본값으로 그대로 둘 수 있습니다. 저장을 선택하고 다음 섹션으로 이동하기 전에 설정이 완료될 때까지 기다립니다.

    포털에서 파일 업로드 설정 확인을 보여 주는 화면 캡처.

Azure Storage 계정을 만드는 방법에 대한 자세한 지침은 스토리지 계정 만들기를 참조하세요. 스토리지 계정 및 Blob 컨테이너를 IoT 허브와 연결하는 방법에 대한 자세한 지침은 Azure Portal을 사용하여 파일 업로드 구성을 참조하세요.

디바이스 앱에서 파일 업로드

이 섹션에서는 IoT 허브에 파일을 업로드하는 디바이스 앱을 만듭니다. 코드는 Azure IoT Node.js SDK 디바이스 샘플의 upload_to_blob_advanced.js 샘플에서 사용할 수 있는 코드를 기반으로 합니다.

  1. fileupload라는 빈 폴더를 만듭니다. fileupload 폴더의 명령 프롬프트에서 다음 명령을 사용하여 package.json 파일을 만듭니다. 모든 기본값을 수락합니다.

    npm init
    
  2. 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
    
  3. 텍스트 편집기를 사용하여 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();
      });
    
  4. FileUpload.js 파일을 저장하고 닫습니다.

  5. 이미지 파일을 fileupload 폴더에 복사하고 myimage.png와 같은 이름을 지정합니다.

  6. 디바이스 연결 문자열에 대한 환경 변수와 업로드할 파일의 경로를 추가합니다. 디바이스 연결 문자열은 IoT Hub에서 디바이스를 등록할 때 얻은 것입니다.

    • 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 Hub 연결 문자열 가져오기

이 문서에서는 사용자가 만든 IoT 허브에서 파일 업로드 알림 메시지를 수신하는 백 엔드 서비스를 만듭니다. 파일 업로드 알림 메시지를 수신하려면 서비스에 서비스 연결 권한이 있어야 합니다. 기본적으로 모든 IoT Hub는 이 사용 권한을 부여하는 service라는 공유 액세스 정책을 사용하여 만듭니다.

service 정책에 대한 IoT Hub 연결 문자열을 가져오려면 다음 단계를 수행합니다.

  1. Azure Portal에서 리소스 그룹을 선택합니다. 허브가 있는 리소스 그룹을 선택한 다음, 리소스 목록에서 허브를 선택합니다.

  2. IoT Hub의 왼쪽 창에서 공유 액세스 정책을 선택합니다.

  3. 정책 목록에서 ervice 정책을 선택합니다.

  4. 기본 연결 문자열을 복사하고 값을 저장합니다.

Azure Portal의 IoT Hub에서 연결 문자열을 검색하는 방법을 보여 주는 스크린샷.

IoT Hub 공유 액세스 정책 및 사용 권한에 대한 자세한 내용은 액세스 제어 및 권한을 참조하세요.

파일 업로드 알림 수신

이 섹션에서는 IoT Hub로부터 파일 업로드 알림 메시지를 수신하는 Node.js 콘솔 앱을 만듭니다.

  1. fileuploadnotification라는 빈 폴더를 만듭니다. fileuploadnotification 폴더의 명령 프롬프트에서 다음 명령을 사용하여 package.json 파일을 만듭니다. 모든 기본값을 수락합니다.

    npm init
    
  2. fileuploadnotification 폴더의 명령 프롬프트에서 다음 명령을 실행하여 azure-iothub SDK 패키지를 설치합니다.

    npm install azure-iothub --save
    
  3. 텍스트 편집기를 사용하여 fileuploadnotification 폴더에 FileUploadNotification.js 파일을 만듭니다.

  4. FileUploadNotification.js 파일의 시작 부분에 다음 require 문을 추가합니다.

    'use strict';
    
    const Client = require('azure-iothub').Client;
    
  5. 환경에서 IoT 허브에 대한 연결 문자열을 읽습니다.

    const connectionString = process.env.IOT_HUB_CONNECTION_STRING;
    
  6. 다음 코드를 추가하여 연결 문자열에서 서비스 클라이언트를 만듭니다.

    const serviceClient = Client.fromConnectionString(connectionString);
    
  7. 클라이언트를 열고 상태 업데이트를 수신하는 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.complete(msg, function (err) {
                if (err) {
                  console.error('Could not finish the upload: ' + err.message);
                } else {
                  console.log('Upload complete');
                }
              });
            });
          }
        });
      }
    });
    

    참고 항목

    파일 업로드 알림을 수신하는 동안 연결 해제 알림을 받으려면 receiver.on을 사용하여 'error'를 등록해야 합니다. 파일 업로드 알림을 계속 받으려면 serviceClient.open 메서드를 사용하여 IoT Hub에 다시 연결해야 합니다.

  8. FileUploadNotification.js 파일을 저장하고 닫습니다.

  9. IoT Hub 연결 문자열의 환경 변수를 추가합니다. 이 문자열은 이전에 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.windows.net/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"}

파일 업로드 확인

포털을 사용하면 구성한 스토리지 컨테이너에 업로드된 파일을 볼 수 있습니다.

  1. Azure Portal에서 스토리지 계정으로 이동합니다.

  2. 스토리지 계정의 왼쪽 창에서 컨테이너를 선택합니다.

  3. 파일을 업로드한 컨테이너를 선택합니다.

  4. 디바이스 이름을 딴 폴더를 선택합니다.

  5. 파일을 업로드한 Blob을 선택합니다. 이 문서에서는 파일과 동일한 이름의 Blob입니다.

    Azure Portal에서 업로드된 파일을 보여 주는 스크린샷

  6. 열리는 페이지에서 Blob 속성을 확인합니다. 다운로드를 선택하여 파일을 다운로드하고 로컬에서 파일 내용을 볼 수 있습니다.

다음 단계

이 문서에서는 디바이스에서 파일 업로드를 단순화하기 위해 IoT Hub의 파일 업로드 기능을 사용하는 방법을 알아보았습니다. 다음 문서에서 이 기능을 계속 탐색할 수 있습니다.