파일을 업로드하는 방법(HTML)

[ 이 문서는 Windows 런타임 앱을 작성하는 Windows에서 8.x 및 Windows Phone 8.x 개발자를 대상으로 합니다. Windows 10용으로 개발하는 경우에는 최신 설명서를 참조하세요.]

이 항목에서는 장치에서 인터넷으로 데이터나 파일을 업로드하는 방법을 보여 줍니다.

앱은 이 항목에서 설명하는 API를 사용하여 앱에서 웹 서비스를 조작하여 사진, 음악, 동영상 등과 같은 주요 미디어 형식을 사용하거나 공유하도록 설정할 수 있습니다.

작업 수명 주기 동안 앱이 여러 번 일시 중단되거나 네트워크 가용성이 변경되는 대용량, 스트림 기반 또는 다중 파트 전송(동영상, 음악, 큰 이미지)의 경우 앱에서 Background Transfer를 사용할 수 있습니다.

백그라운드 전송에 대한 자세한 내용은 백그라운드로 데이터 전송을 참조하세요.

사전 요구 사항

JavaScript Windows 스토어 앱 만들기에 대한 일반적인 도움말은 JavaScript를 사용하여 첫 번째 Windows 런타임 앱 만들기를 참조하세요. 또한 JavaScript Promise는 이 항목에서 비동기 작업을 완료하는 데 사용됩니다. 이 프로그래밍 패턴에 대한 자세한 내용은 Promises를 사용하는 JavaScript의 비동기 프로그래밍을 참조하세요.

앱이 네트워크에 대비하도록 하려면 프로젝트 Package.appxmanifest 파일에서 접근 권한 값을 설정해야 합니다. 각 네트워크 접근 권한 값에 대한 정의는 네트워크 격리 접근 권한 값을 구성하는 방법을 참조하세요.

다음 백그라운드 전송 예는 JavaScript를 사용하며 백그라운드 전송 샘플(영문)을 기반으로 합니다.

백그라운드 전송 업로드 작업

백그라운드 전송을 사용할 경우 업로드는 작업을 다시 시작하거나 취소하는 데 사용된 많은 컨트롤 메서드를 노출하는 UploadOperation으로 존재합니다. 앱 이벤트(예: 일시 중단 또는 종료) 및 연결 변경은 UploadOperation별로 자동으로 처리되며 업로드는 앱 일시 중단 또는 일시 중지 중에도 계속되며 앱 종료 후에도 유지됩니다. 또한 CostPolicy 속성을 설정하여 데이터 통신 연결 네트워크로 인터넷에 연결한 동안 앱에서 업로드를 시작할지를 나타냅니다.

다음 예에서는 기본 업로드를 만들고 초기화하는 방법과 이전 앱 세션의 지속형 작업을 열거 및 다시 시도하는 방법을 안내합니다.

파일 업로드

업로드 만들기는 BackgroundUploader로 시작합니다. 이 클래스는 결과 UploadOperation 개체를 만들기 전에 앱에서 업로드를 구성할 수 있는 방법을 제공합니다. 다음 예에서는 필요한 UriStorageFile 개체를 사용하여 이 작업을 수행하는 방법을 보여 줍니다.

  1. 파일 및 업로드 대상 식별

    UploadOperation 만들기를 시작하려면 먼저 업로드할 위치의 URI 및 업로드할 파일을 식별해야 합니다. 다음 예에서는 UI 입력의 문자열을 사용하여 uriString 값을 채우고 PickSingleFileAsync 작업에서 반환한 StorageFile 개체를 사용하여 file 값을 채웁니다.

    function uploadFile() {
        var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
        filePicker.fileTypeFilter.replaceAll(["*"]);
    
        filePicker.pickSingleFileAsync().then(function (file) {
            if (!file) {
                printLog("No file selected");
                return;
            }
    
            var upload = new UploadOp();
            var uriString = document.getElementById("serverAddressField").value;
            upload.start(uriString, file);
    
            // Store the upload operation in the uploadOps array.
            uploadOperations.push(upload);
        });
    }
    
  2. 업로드 작업 만들기 및 초기화

    이전 단계에서는 uriStringfile 값을 다음 예 UploadOp의 인스턴스에 전달하여 새로운 업로드 작업을 구성하고 시작하는 데 사용합니다. 먼저 uriString을 구문 분석하여 필요한 Uri 개체를 만듭니다.

    그런 다음 제공된 StorageFile(file)의 속성을 BackgroundUploader에서 사용하여 요청 헤더를 채우고 SourceFile 속성을 StorageFile 개체로 설정합니다. 그런 다음 문자열로 제공된 파일 이름 정보 및 StorageFile.Name 속성을 삽입하도록 SetRequestHeader 메서드가 호출됩니다.

    마지막으로 BackgroundUploader에서 UploadOperation(upload)을 만듭니다.

    function UploadOp() {
        var upload = null;
        var promise = null;
    
        this.start = function (uriString, file) {
            try {
    
                var uri = new Windows.Foundation.Uri(uriString);
                var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
    
                // Set a header, so the server can save the file (this is specific to the sample server).
                uploader.setRequestHeader("Filename", file.name);
    
                // Create a new upload operation.
                upload = uploader.createUpload(uri, file);
    
                // Start the upload and persist the promise to be able to cancel the upload.
                promise = upload.startAsync().then(complete, error, progress);
            } catch (err) {
                displayError(err);
            }
        };
        // On application activation, reassign callbacks for a upload
        // operation persisted from previous application state.
        this.load = function (loadedUpload) {
            try {
                upload = loadedUpload;
                promise = upload.attachAsync().then(complete, error, progress);
            } catch (err) {
                displayError(err);
            }
        };
    }
    

    JavaScript Promise를 사용하여 정의된 비동기 메서드 호출에 유의하세요. 마지막 예제에서 다음 줄을 봅니다.

    promise = upload.startAsync().then(complete, error, progress);
    

    비동기 메서드 호출 뒤에 then 문이 오며, 비동기 메서드 호출에서 결과가 반환되면 호출되는, 앱에 의해 정의된 메서드를 나타냅니다. 이 프로그래밍 패턴에 대한 자세한 내용은 Promises를 사용하는 JavaScript의 비동기 프로그래밍을 참조하세요.

여러 파일 업로드

  1. 파일 및 업로드 대상 식별

    단일 UploadOperation으로 여러 파일을 전송하는 시나리오에서, 프로세스는 주로 요청된 대상 URI 및 로컬 파일 정보를 처음 제공하여 수행할 때 시작됩니다. 이전 섹션의 예제에서처럼, URI는 최종 사용자에 의해 문자열로 제공되며 FileOpenPicker는 사용자 인터페이스를 통해 파일을 지정하는 기능을 제공하는 데도 사용할 수 있습니다. 그러나 대신 이 시나리오에서는 UI를 통해 여러 파일을 선택할 수 있도록 앱이 PickMultipleFilesAsync 메서드를 호출해야 합니다.

    
    function uploadFiles() {
       var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
       filePicker.fileTypeFilter.replaceAll(["*"]);
    
       filePicker.pickMultipleFilesAsync().then(function (files) {
          if (files === 0) {
             printLog("No file selected");
                return;
          }
    
          var upload = new UploadOperation();
          var uriString = document.getElementById("serverAddressField").value;
          upload.startMultipart(uriString, files);
    
          // Persist the upload operation in the global array.
          uploadOperations.push(upload);
       });
    }
    
  2. 제공된 매개 변수에 대한 개체 만들기

    다음 두 예제에서는 마지막 단계의 끝에 호출된 단일 예제 메서드 startMultipart에 포함된 코드를 사용합니다. 이해를 돕기 위해 BackgroundTransferContentPart 개체의 배열을 만드는 메서드의 코드는 결과 UploadOperation을 만드는 코드에서 분리되었습니다.

    먼저, 사용자가 제공한 URI가 Uri로 초기화됩니다. 다음으로, 이 메서드에 전달된 IStorageFile 개체의 배열(files)에서 반복 작업이 수행되며, 각 개체는 contentParts 배열에 포함될 새 BackgroundTransferContentPart 개체를 만드는 데 사용됩니다.

    
    upload.startMultipart = function (uriString, files) {
        try {
            var uri = new Windows.Foundation.Uri(uriString);
            var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
    
            var contentParts = [];
            files.forEach(function (file, index) {
                var part = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart("File" + index, file.name);
                part.setFile(file);
                contentParts.push(part);
            });
    
  3. 다중 파트 업로드 작업 만들기 및 초기화

    업로드할 각 IStorageFile을 나타내는 모든 BackgroundTransferContentPart 개체로 채워진 contentParts 배열이 만들어지면 요청이 보내질 위치를 나타내는 Uri를 사용하여 CreateUploadAsync를 호출할 준비가 된 것입니다.

            // Create a new upload operation.
            uploader.createUploadAsync(uri, contentParts).then(function (uploadOperation) {
    
               // Start the upload and persist the promise to be able to cancel the upload.
               upload = uploadOperation;
               promise = uploadOperation.startAsync().then(complete, error, progress);
            });
    
         } catch (err) {
             displayError(err);
         }
     };
    

시작할 때 지속형 작업 열거

UploadOperation의 완료 또는 취소 시, 연결된 시스템 리소스가 해제됩니다. 그러나 완료 또는 취소가 발생하기 전에 앱이 종료되는 경우 활성 작업은 중단되지만 연결된 리소스는 그대로 유지됩니다. 작업이 열거되지 않아서 다음 앱 세션에 다시 사용되지 않을 경우 작업이 완료되지 않고 장치 리소스를 계속해서 차지하게 됩니다.

  1. 지속형 작업을 열거하는 함수를 정의하기 전에 다음과 같이 반환될 UploadOperation 개체를 포함할 배열을 만들어야 합니다.

    var uploadOperations = [];
    
  2. 그런 다음 지속형 작업을 열거하고 배열에 저장하는 함수를 정의합니다. UploadOperation에 콜백을 다시 할당하기 위해 호출되는 load 메서드는 앱 종료 기간 동안 지속될 경우 이 섹션의 뒷 부분에서 정의하는 UploadOp 클래스에 있습니다.

    function Windows.Networking.BackgroundTransfer.BackgroundUploader.getCurrentUploadsAsync() {
        .then(function (uploads) {
            for (var i = 0; i < uploads.size; i++) {
                var upload = new UploadOp();
                upload.load(uploads[i]);
                uploadOperations.push(upload);
            }
        }
    };
    

    참고  

    Windows Phone 스토어 앱에서는 앱이 포그라운드에 없는 경우에도 백그라운드 전송이 계속 진행됩니다. 이 시나리오에서는 앱이 실행되고 있지 않으므로 전송이 완료되어도 알림을 받지 못합니다. 앱이 다시 시작될 때 완료된 전송의 진행률을 확인하면 상태가 BackgroundTransferStatus.Running입니다. 그러나 위의 코드 예제처럼 전송에 연결하면 작업 완료 처리기가 발생되고 전송 상태가 업데이트됩니다.

요청 시간 제한

두 가지 주요 연결 시간 제한 시나리오를 고려해야 합니다.

  • 전송을 위해 새 연결을 설정할 때 5분 이내에 연결이 설정되지 않을 경우 연결 요청이 중단됩니다.

  • 연결이 설정되면 2분 이내에 응답을 받지 못한 모든 HTTP 요청 메시지가 중단됩니다.

참고  두 경우 모두 인터넷 연결이 있고 백그라운드 전송에서 요청을 최대 세 번까지 자동으로 다시 시도한다고 가정합니다. 인터넷 연결이 검색되지 않는 경우 추가 요청은 인터넷에 연결될 때까지 대기합니다.

 

디버깅 지침

Microsoft Visual Studio에서 디버깅 세션을 중지하는 것은 앱을 닫는 것과 같습니다. PUT 업로드가 일시 중지되고 POST 업로드가 종료됩니다. 디버깅 중에도 앱이 지속형 업로드를 열거한 다음 다시 시작하거나 취소해야 합니다. 예를 들어 해당 디버그 세션의 이전 작업에 관심이 없는 경우 앱을 시작할 때 앱에서 열거된 지속형 업로드 작업을 취소하도록 할 수 있습니다.

디버그 세션의 이전 작업에 관심이 없는 경우 디버그 세션 중 앱을 시작할 때 다운로드/업로드를 열거하는 동안 앱에서 취소하도록 할 수 있습니다. 앱 매니페스트 변경 등의 Visual Studio 프로젝트 업데이트가 있으며 앱을 제거하고 다시 배포하는 경우에는 GetCurrentUploadsAsync에서 이전 앱 배포를 사용하여 만든 작업을 열거할 수 없습니다.

자세한 내용은 Windows 스토어 앱 디버깅 및 테스트를 참조하세요.

개발 중 백그라운드 전송을 사용하는 경우 활성 및 완료된 전송 작업의 내부 캐시가 동기화되지 않는 상황이 발생할 수 있습니다. 이 경우 새 전송 작업을 시작하거나 기존 작업 및 BackgroundTransferGroup 개체를 조작하지 못할 수 있습니다. 기존 작업을 조작할 때 크래시가 트리거되는 경우도 있습니다. TransferBehavior 속성이 Parallel로 설정된 경우 이러한 결과가 발생할 수 있습니다. 이 문제는 개발 중 특정 시나리오에서만 발생하며 앱의 최종 사용자에게는 해당하지 않습니다.

Visual Studio를 사용한 네 가지 시나리오에서 이 문제가 발생할 수 있습니다.

  • 기존 프로젝트와 앱 이름은 같지만 다른 언어(예: C++에서 C#으로 변경)로 새 프로젝트를 만듭니다.
  • 기존 프로젝트에서 대상 아키텍처를 변경합니다(예: x86에서 x64로 변경).
  • 기존 프로젝트에서 문화권을 변경합니다(예: 중립에서 en-US로 변경).
  • 기존 프로젝트의 패키지 매니페스트에서 접근 권한 값을 추가하거나 제거합니다(예: 엔터프라이즈 인증 추가).

접근 권한 값을 추가하거나 제거하는 매니페스트 업데이트를 비롯한 정기 앱 서비스는 앱의 최종 사용자 배포에서 이 문제를 트리거하지 않습니다.

이 문제를 해결하려면 앱의 모든 버전을 완전히 제거하고 새로운 언어, 아키텍처, 문화권 또는 접근 권한 값으로 다시 배포합니다. 시작 화면이나 PowerShell 및 Remove-AppxPackage cmdlet을 사용하여 이 작업을 수행할 수 있습니다.

요약 및 다음 단계

이 항목에서는 JavaScript에서 Background Transfer API를 사용하여 파일을 업로드하는 방법을 검토했습니다.

또한 Windows 스토어 앱에 파일을 다운로드할 수 있습니다. 핵심 개념과 예제에 대한 자세한 내용은 파일을 다운로드하는 방법을 참조하세요.

관련 항목

기타

연결 및 데이터 계획 정보 액세스

promises를 사용한 JavaScript의 비동기 프로그래밍

JavaScript를 사용하여 첫 Windows 런타임 앱 만들기

네트워크 접근 권한 값을 구성하는 방법

WinJS xhr을 사용하여 파일을 다운로드하는 방법

참조

BackgroundUploader

UploadOperation

Windows.Networking.BackgroundTransfer

샘플

백그라운드 전송 샘플

HttpClient 샘플

파일을 다운로드하는 방법

Windows.Networking.BackgroundTransfer

백그라운드 전송 샘플