Node.js 용 클라이언트 라이브러리를 사용 하 여 blob 업로드, 다운로드 및 나열Upload, download, and list blobs using the client library for Node.js

이 가이드에서는 Node.js v2용 클라이언트 라이브러리를 사용하여 Blob을 업로드 및 다운로드하고 Azure Blob 스토리지와 함께 나열하는 방법에 대해 알아봅니다.In this how-to guide, you learn how to use the client library for Node.js v2 to upload, download, and list blobs with Azure Blob storage.

Node.js용 Azure Storage 클라이언트 라이브러리의 최신 버전은 v10입니다.The latest version of the Azure Storage client library for Node.js is v10. 가능한 경우 클라이언트 라이브러리의 최신 버전을 사용 하는 것이 좋습니다.Microsoft recommends that you use the latest version of the client library when possible. v10을 사용하여 시작하려면 빠른 시작: JavaScript용 Azure Storage 클라이언트 라이브러리 v10을 사용하여 Blob 업로드, 다운로드, 나열 및 삭제(미리 보기)를 참조하세요.To get started using v10, see Quickstart: Upload, download, list, and delete blobs using Azure Storage client library for JavaScript v10 (preview).

사전 요구 사항Prerequisites

Azure 구독이 아직 없는 경우 시작하기 전에 체험 계정을 만듭니다.If you don't have an Azure subscription, create a free account before you begin.

Azure Portal에서 Azure Storage 계정을 만듭니다.Create an Azure storage account in the Azure portal. 스토리지 계정을 만드는 데 도움이 필요한 경우 스토리지 계정 만들기를 참조하세요.For help creating the account, see Create a storage account.

샘플 애플리케이션 다운로드Download the sample application

샘플 애플리케이션은 간단한 Node.js 콘솔 애플리케이션입니다.The sample application is a simple Node.js console application. 시작하려면 다음 명령을 사용하여 리포지토리를 컴퓨터에 복제합니다.To begin, clone the repository to your machine using the following command:

git clone https://github.com/Azure-Samples/storage-blobs-node-quickstart.git

애플리케이션을 열려면 storage-blobs-node-quickstart 폴더를 찾아 즐겨찾는 코드 편집 환경에서 엽니다.To open the application, look for the storage-blobs-node-quickstart folder and open it in your favorite code editing environment.

Azure Portal에서 자격 증명 복사Copy your credentials from the Azure portal

애플리케이션 예제는 스토리지 계정에 대한 액세스를 인증해야 합니다.The sample application needs to authenticate access to your storage account. 인증하려면 연결 문자열로 애플리케이션에 스토리지 계정 자격 증명을 추가합니다.To authenticate, add your storage account credentials to the application as a connection string. 다음 단계를 수행하여 스토리지 계정 자격 증명을 봅니다.View your storage account credentials by following these steps:

  1. Azure Portal에 로그인합니다.Sign in to the Azure portal.

  2. 스토리지 계정을 찾습니다.Locate your storage account.

  3. 스토리지 계정 개요의 설정 섹션에서 액세스 키를 선택합니다.In the Settings section of the storage account overview, select Access keys. 여기에서 계정 액세스 키 및 각 키의 전체 연결 문자열을 볼 수 있습니다.Here, you can view your account access keys and the complete connection string for each key.

  4. key1 아래에서 연결 문자열 값을 찾고, 복사 단추를 선택하여 연결 문자열을 복사합니다.Find the Connection string value under key1, and select the Copy button to copy the connection string. 다음 단계에서 연결 문자열 값을 환경 변수에 추가합니다.You will add the connection string value to an environment variable in the next step.

    Azure Portal에서 연결 문자열을 복사하는 방법을 보여주는 스크린샷

스토리지 연결 문자열 구성Configure your storage connection string

애플리케이션을 실행하기 전에 스토리지 계정에 대한 연결 문자열을 제공해야 합니다.Before running the application, you must provide the connection string for your storage account. 샘플 리포지토리에는 .env.example이라는 파일이 포함되어 있습니다.The sample repository includes a file named .env.example. .example 확장명을 제거하여 .env 파일이 되도록 이 파일의 이름을 바꿀 수 있습니다.You can rename this file by removing the .example extension, which results in a file named .env. .env 파일 내에서 AZURE_STORAGE_CONNECTION_STRING 키 뒤에 연결 문자열 값을 추가합니다.Inside the .env file, add your connection string value after the AZURE_STORAGE_CONNECTION_STRING key.

필요한 패키지를 설치합니다.Install required packages

애플리케이션 디렉터리에서 npm install을 실행하여 애플리케이션에 필요한 패키지를 설치합니다.In the application directory, run npm install to install the required packages for the application.

npm install

샘플 실행Run the sample

이제 종속성이 설치되었으므로 다음 명령을 발행하여 샘플을 실행할 수 있습니다.Now that the dependencies are installed, you can run the sample by issuing the following command:

npm start

이 스크립트의 출력은 다음과 유사합니다.The output from the script will be similar to the following:

Containers:
 - container-one
 - container-two
Container "demo" is created
Blob "quickstart.txt" is uploaded
Local file "./readme.md" is uploaded
Blobs in "demo" container:
 - quickstart.txt
 - readme.md
Blob downloaded blob content: "hello Blob SDK"
Blob "quickstart.txt" is deleted
Container "demo" is deleted
Done

이 예제에서 새로운 스토리지 계정을 사용할 경우 “Containers”라는 레이블 아래에 나열된 컨테이너 이름이 보이지 않을 수 있습니다.If you are using a new storage account for this example, then you may not see any container names listed under the label "Containers".

코드 이해Understanding the code

첫 번째 식은 환경 변수로 값을 로드하는 데 사용됩니다.The first expression is used to load values into environment variables.

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').load();
}

dotenv 모듈은 로컬에서 디버깅을 위해 앱을 실행할 때 환경 변수를 로드합니다.The dotenv module loads environment variables when running the app locally for debugging. 값은 .env라는 파일에 정의되고, 현재 실행 컨텍스트에 로드됩니다.Values are defined in a file named .env and loaded into the current execution context. 프로덕션 컨텍스트에서는 서버 구성이 이러한 값을 제공하므로 스크립트가 "프로덕션" 컨텍스트에서 실행되고 있지 않을 때만 이 코드가 실행됩니다.In production contexts, the server configuration provides these values and that is why this code is only run when the script is not running under a "production" context.

const path = require('path');
const storage = require('azure-storage');

모듈의 용도는 다음과 같습니다.The purpose of the modules is as follows:

.env라는 파일을 현재 실행 컨텍스트로file named .env into the current execution context

다음으로, blobService 변수는 Azure Blob Service의 새 인스턴스로 초기화됩니다.Next, the blobService variable is initialized as a new instance of the Azure Blob service.

const blobService = storage.createBlobService();

다음 구현에서는 Azure Storage API의 콜백 특성을 간소화하기 위해 각 blobService 함수가 Promise에 래핑되어 JavaScript의 async 함수와 await 연산자에 액세스할 수 있습니다.In the following implementation, each of the blobService functions is wrapped in a Promise, which allows access to JavaScript's async function and await operator to streamline the callback nature of the Azure Storage API. 각 함수에 대한 응답이 성공적으로 반환되면, 프라미스에서 작업과 관련된 메시지와 함께 관련 데이터를 사용하여 확인합니다.When a successful response returns for each function, the promise resolves with relevant data along with a message specific to the action.

컨테이너 나열List containers

listContainers 함수는 그룹의 컨테이너 컬렉션을 반환하는 listContainersSegmented를 호출합니다.The listContainers function calls listContainersSegmented which returns collections of containers in groups.

const listContainers = async () => {
    return new Promise((resolve, reject) => {
        blobService.listContainersSegmented(null, (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `${data.entries.length} containers`, containers: data.entries });
            }
        });
    });
};

그룹의 크기는 ListContainersOptions를 통해 구성할 수 있습니다.The size of the groups is configurable via ListContainersOptions. listContainersSegmented를 호출하면 Blob 메타데이터가 ContainerResult 인스턴스의 배열로 반환됩니다.Calling listContainersSegmented returns blob metadata as an array of ContainerResult instances. 결과는 5,000개의 증분 일괄 처리(세그먼트)로 반환됩니다.Results are returned in 5,000 increment batches (segments). 컨테이너에 5,000개보다 많은 Blob이 있는 경우 continuationToken에 대한 값이 결과에 포함됩니다.If there are more than 5,000 blobs in a container, then the results include a value for continuationToken. Blob 컨테이너에서 후속 세그먼트를 나열하려면 연속 토큰을 두 번째 인수로 listContainersSegment에 다시 전달할 수 있습니다.To list subsequent segments from the blob container, you can pass the continuation token back into listContainersSegment as the second argument.

컨테이너 만들기Create a container

createContainer 함수는 createContainerIfNotExists를 호출하고 Blob에 적절한 액세스 수준을 설정합니다.The createContainer function calls createContainerIfNotExists and sets the appropriate access level for the blob.

const createContainer = async (containerName) => {
    return new Promise((resolve, reject) => {
        blobService.createContainerIfNotExists(containerName, { publicAccessLevel: 'blob' }, err => {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `Container '${containerName}' created` });
            }
        });
    });
};

createContainerIfNotExists에 대한 두 번째 매개 변수(options)는 publicAccessLevel에 대한 값을 수락합니다.The second parameter (options) for createContainerIfNotExists accepts a value for publicAccessLevel. publicAccessLevel에 대한 blob 값은 특정 Blob 데이터가 공개적으로 노출되도록 지정합니다.The value blob for publicAccessLevel specifies that specific blob data is exposed to the public. 이 설정은 컨테이너 수준 액세스와 달리 컨테이너의 내용을 나열하는 기능을 부여합니다.This setting is in contrast to container level access, which grants the ability to list the contents of the container.

createContainerIfNotExists를 사용하면 컨테이너가 이미 있을 때 애플리케이션에서 오류를 반환하지 않고 createContainer 명령을 여러 번 실행할 수 있습니다.The use of createContainerIfNotExists allows the application to run the createContainer command multiple times without returning errors when the container already exists. 프로덕션 환경에서는 애플리케이션 전체에서 동일한 컨테이너가 사용되므로 createContainerIfNotExists만 호출하는 경우가 많습니다.In a production environment, you often only call createContainerIfNotExists once as the same container is used throughout the application. 이러한 경우 포털 또는 Azure CLI를 통해 컨테이너를 미리 만들 수 있습니다.In these cases, you can create the container ahead of time through the portal or via the Azure CLI.

텍스트 업로드Upload text

uploadString 함수는 createBlockBlobFromText를 호출하여 Blob 컨테이너에 임의 문자열을 쓰거나 덮어씁니다).The uploadString function calls createBlockBlobFromText to write (or overwrite) an arbitrary string to the blob container.

const uploadString = async (containerName, blobName, text) => {
    return new Promise((resolve, reject) => {
        blobService.createBlockBlobFromText(containerName, blobName, text, err => {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `Text "${text}" is written to blob storage` });
            }
        });
    });
};

로컬 파일 업로드Upload a local file

uploadLocalFile 함수는 createBlockBlobFromLocalFile을 사용하여 파일을 파일 시스템에서 Blob Storage에 업로드하고 쓰거나 덮어씁니다.The uploadLocalFile function uses createBlockBlobFromLocalFile to upload and write (or overwrite) a file from the file system into blob storage.

const uploadLocalFile = async (containerName, filePath) => {
    return new Promise((resolve, reject) => {
        const fullPath = path.resolve(filePath);
        const blobName = path.basename(filePath);
        blobService.createBlockBlobFromLocalFile(containerName, blobName, fullPath, err => {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `Local file "${filePath}" is uploaded` });
            }
        });
    });
};

콘텐츠를 Blob에 업로드하는 데 사용할 수 있는 다른 방법은 textstreams를 사용하는 것입니다.Other approaches available to upload content into blobs include working with text and streams. 파일이 Blob 스토리지에 업로드되었는지 확인하려면 Azure Storage Explorer를 사용하여 계정의 데이터를 확인하면 됩니다.To verify the file is uploaded to your blob storage, you can use the Azure Storage Explorer to view the data in your account.

Blob 나열List the blobs

listBlobs 함수는 listBlobsSegmented 메서드를 호출하여 컨테이너의 Blob 메타데이터 목록을 반환합니다.The listBlobs function calls the listBlobsSegmented method to return a list of blob metadata in a container.

const listBlobs = async (containerName) => {
    return new Promise((resolve, reject) => {
        blobService.listBlobsSegmented(containerName, null, (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `${data.entries.length} blobs in '${containerName}'`, blobs: data.entries });
            }
        });
    });
};

listBlobsSegmented를 호출하면 Blob 메타데이터가 BlobResult 인스턴스의 배열로 반환됩니다.Calling listBlobsSegmented returns blob metadata as an array of BlobResult instances. 결과는 5,000개의 증분 일괄 처리(세그먼트)로 반환됩니다.Results are returned in 5,000 increment batches (segments). 컨테이너에 5,000개보다 많은 Blob이 있는 경우 continuationToken에 대한 값이 결과에 포함됩니다.If there are more than 5,000 blobs in a container, then the results include a value for continuationToken. Blob 컨테이너에서 후속 세그먼트를 나열하려면 연속 토큰을 두 번째 인수로 listBlobSegmented에 다시 전달할 수 있습니다.To list subsequent segments from the blob container, you can pass the continuation token back into listBlobSegmented as the second argument.

Blob 다운로드Download a blob

downloadBlob 함수는 getBlobToText를 사용하여 Blob의 내용을 지정된 절대 파일 경로로 다운로드합니다.The downloadBlob function uses getBlobToText to download the contents of the blob to the given absolute file path.

const downloadBlob = async (containerName, blobName) => {
    const dowloadFilePath = path.resolve('./' + blobName.replace('.txt', '.downloaded.txt'));
    return new Promise((resolve, reject) => {
        blobService.getBlobToText(containerName, blobName, (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `Blob downloaded "${data}"`, text: data });
            }
        });
    });
};

여기에 표시된 구현은 원본을 변경하고, Blob의 콘텐츠를 문자열로 반환합니다.The implementation shown here changes the source returns the contents of the blob as a string. 또한 Blob를 스트림 으로 다운로드하거나 로컬 파일에 직접 다운로드할 수도 있습니다.You can also download the blob as a stream as well as directly to a local file.

Blob 삭제Delete a blob

deleteBlob 함수는 deleteBlobIfExists 함수를 호출합니다.The deleteBlob function calls the deleteBlobIfExists function. 이름에서 알 수 있듯이 이 함수는 Blob이 이미 삭제된 오류를 반환하지 않습니다.As the name implies, this function does not return an error if the blob is already deleted.

const deleteBlob = async (containerName, blobName) => {
    return new Promise((resolve, reject) => {
        blobService.deleteBlobIfExists(containerName, blobName, err => {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `Block blob '${blobName}' deleted` });
            }
        });
    });
};

컨테이너 삭제Delete a container

Blob Service에서 deleteContainer 메소드를 호출하고 컨테이너 이름에 전달하면 컨테이너가 삭제됩니다.Containers are deleted by calling the deleteContainer method off the blob service and passing in the container name.

const deleteContainer = async (containerName) => {
    return new Promise((resolve, reject) => {
        blobService.deleteContainer(containerName, err => {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `Container '${containerName}' deleted` });
            }
        });
    });
};

코드 호출Calling code

JavaScript의 async/await 구문을 지원하기 위해 모든 호출 코드는 execute라는 함수에 래핑됩니다.In order to support JavaScript's async/await syntax, all the calling code is wrapped in a function named execute. 그런 다음 execute가 호출되고 promise로 처리됩니다.Then execute is called and handled as a promise.

async function execute() {
    // commands 
}

execute().then(() => console.log("Done")).catch((e) => console.log(e));

다음 코드는 모두 // commands 주석이 있는 execute 함수 내에서 실행됩니다.All of the following code runs inside the execute function where the // commands comment is placed.

먼저 이름, 샘플 콘텐츠를 할당하고 Blob Storage에 업로드할 로컬 파일을 가리키는 관련 변수가 선언됩니다.First, the relevant variables are declared to assign names, sample content and to point to the local file to upload to Blob storage.

const containerName = "demo";
const blobName = "quickstart.txt";
const content = "hello Node SDK";
const localFilePath = "./readme.md";
let response;

스토리지 계정의 컨테이너를 나열하기 위해 listContainers 함수가 호출되고 반환된 컨테이너 목록이 출력 창에 기록됩니다.To list the containers in the storage account, the listContainers function is called and the returned list of containers is logged to the output window.

console.log("Containers:");
response = await listContainers();
response.containers.forEach((container) => console.log(` -  ${container.name}`));

컨테이너 목록이 표시되면 Array findIndex 메서드를 사용하여 만들려는 컨테이너가 이미 있는지 확인할 수 있습니다.Once the list of containers is available, then you can use the Array findIndex method to see if the container you want to create already exists. 컨테이너가 없으면 컨테이너가 생성됩니다.If the container does not exist then the container is created.

const containerDoesNotExist = response.containers.findIndex((container) => container.name === containerName) === -1;

if (containerDoesNotExist) {
    await createContainer(containerName);
    console.log(`Container "${containerName}" is created`);
}

다음으로, 문자열 및 로컬 파일이 Blob Storage에 업로드됩니다.Next, a string and a local file is uploaded to Blob storage.

await uploadString(containerName, blobName, content);
console.log(`Blob "${blobName}" is uploaded`);

response = await uploadLocalFile(containerName, localFilePath);
console.log(response.message);

Blob을 나열하는 프로세스는 컨테이너를 나열하는 프로세스와 동일합니다.The process to list blobs is the same as listing containers. listBlobs를 호출하면 컨테이너의 Blob 배열이 반환되어 출력 창에 기록됩니다.The call to listBlobs returns an array of blobs in the container and are logged to the output window.

console.log(`Blobs in "${containerName}" container:`);
response = await listBlobs(containerName);
response.blobs.forEach((blob) => console.log(` - ${blob.name}`));

Blob을 다운로드하기 위해 응답이 캡처되고 Blob 값에 액세스하는 데 사용됩니다.To download a blob, the response is captured and used to access the value of the blob. 응답에서 readableStreamBody가 문자열로 변환되어 출력 창에 기록됩니다.From the response readableStreamBody is converted to a string and logged out to the output window.

response = await downloadBlob(containerName, blobName);
console.log(`Downloaded blob content: "${response.text}"`);

마지막으로, Blob 및 컨테이너가 스토리지 계정에서 삭제됩니다.Finally, the blob and container are deleted from the storage account.

await deleteBlob(containerName, blobName);
console.log(`Blob "${blobName}" is deleted`);

await deleteContainer(containerName);
console.log(`Container "${containerName}" is deleted`);

리소스 정리Clean up resources

스토리지 계정에 기록된 모든 데이터는 코드 샘플 끝 부분에서 자동으로 삭제됩니다.All data written to the storage account is automatically deleted at the end of the code sample.

BLOB을 사용하여 Node.js 애플리케이션을 개발하기 위한 리소스Resources for developing Node.js applications with blobs

Blob Storage를 사용하여 Node.js 응용 프로그램을 개발하기 위한 추가 리소스는 다음과 같습니다.See these additional resources for Node.js development with Blob storage:

이진 파일 및 소스 코드Binaries and source code

클라이언트 라이브러리 참조 및 샘플Client library reference and samples

다음 단계Next steps

이 문서에서는 Node.js를 사용하여 로컬 디스크와 Azure Blob Storage 간에 파일을 업로드하는 방법을 설명합니다.This article demonstrates how to upload a file between a local disk and Azure Blob storage using Node.js. Blob Storage를 사용하는 방법을 자세히 알아보려면 GitHub 리포지토리로 이동하세요.To learn more about working with Blob storage, continue to the GitHub repository.