[http] 한 번의 작업으로 여러 파일 다운로드

표준 웹 기술을 사용하여 이것이 가능한지 확실하지 않습니다.

사용자가 한 번의 작업으로 여러 파일을 다운로드 할 수 있기를 바랍니다. 즉, 파일 옆의 확인란을 클릭 한 다음 확인 된 모든 파일을 가져옵니다.

가능합니까-그렇다면 어떤 기본 전략을 권장합니까? 나는 comets 기술을 사용하여 HttpResponse를 트리거하는 서버 측 이벤트를 만들 수 있다는 것을 알고 있지만 더 간단한 방법이 있기를 바랍니다.



답변

HTTP는 한 번에 둘 이상의 파일 다운로드를 지원하지 않습니다.

두 가지 솔루션이 있습니다.

  • x 개의 창을 열어 파일 다운로드를 시작합니다 (JavaScript로 수행됨).
  • 선호하는 솔루션 파일을 압축하는 스크립트 생성

답변

var links = [
  'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.exe',
  'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.dmg',
  'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.jar'
];

function downloadAll(urls) {
  var link = document.createElement('a');

  link.setAttribute('download', null);
  link.style.display = 'none';

  document.body.appendChild(link);

  for (var i = 0; i < urls.length; i++) {
    link.setAttribute('href', urls[i]);
    link.click();
  }

  document.body.removeChild(link);
}
<button onclick="downloadAll(window.links)">Test me!</button>


답변

숨겨진 iframe의 임시 세트를 만들고, 내부에서 GET 또는 POST로 다운로드를 시작하고, 다운로드가 시작될 때까지 기다렸다가 iframe을 제거 할 수 있습니다.

<!DOCTYPE HTML>
<html>
<body>
  <button id="download">Download</button>

  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
  <script type="text/javascript">

     $('#download').click(function() {
       download('http://nogin.info/cv.doc','http://nogin.info/cv.doc');
     });

     var download = function() {
       for(var i=0; i<arguments.length; i++) {
         var iframe = $('<iframe style="visibility: collapse;"></iframe>');
         $('body').append(iframe);
         var content = iframe[0].contentDocument;
         var form = '<form action="' + arguments[i] + '" method="GET"></form>';
         content.write(form);
         $('form', content).submit();
         setTimeout((function(iframe) {
           return function() {
             iframe.remove();
           }
         })(iframe), 2000);
       }
     }

  </script>
</body>
</html>

또는 jQuery없이 :

 function download(...urls) {
    urls.forEach(url => {
      let iframe = document.createElement('iframe');
      iframe.style.visibility = 'collapse';
      document.body.append(iframe);

      iframe.contentDocument.write(
        `<form action="${url.replace(/\"/g, '"')}" method="GET"></form>`
      );
      iframe.contentDocument.forms[0].submit();

      setTimeout(() => iframe.remove(), 2000);
    });
  }


답변

이 솔루션은 모든 브라우저에서 작동하며 경고를 트리거하지 않습니다. 을 만드는 대신 iframe여기에서 각 파일에 대한 링크를 만듭니다. 이렇게하면 경고 메시지가 표시되지 않습니다.

루핑 부분을 처리하기 위해 setTimeoutIE에서 작동하는 데 필요한를 사용합니다.

/**
 * Download a list of files.
 * @author speedplane
 */
function download_files(files) {
  function download_next(i) {
    if (i >= files.length) {
      return;
    }
    var a = document.createElement('a');
    a.href = files[i].download;
    a.target = '_parent';
    // Use a.download if available, it prevents plugins from opening.
    if ('download' in a) {
      a.download = files[i].filename;
    }
    // Add a to the doc for click to work.
    (document.body || document.documentElement).appendChild(a);
    if (a.click) {
      a.click(); // The click method is supported by most browsers.
    } else {
      $(a).click(); // Backup using jquery
    }
    // Delete the temporary link.
    a.parentNode.removeChild(a);
    // Download the next file with a small timeout. The timeout is necessary
    // for IE, which will otherwise only download the first file.
    setTimeout(function() {
      download_next(i + 1);
    }, 500);
  }
  // Initiate the first download.
  download_next(0);
}
<script>
  // Here's a live example that downloads three test text files:
  function do_dl() {
    download_files([
      { download: "http://www.nt.az/reg.txt", filename: "regs.txt" },
      { download: "https://www.w3.org/TR/PNG/iso_8859-1.txt", filename: "standards.txt" },
      { download: "http://qiime.org/_static/Examples/File_Formats/Example_Mapping_File.txt", filename: "example.txt" },
    ]);
  };
</script>
<button onclick="do_dl();">Test downloading 3 text files.</button>


답변

가장 쉬운 방법은 ZIP 파일로 묶인 여러 파일을 제공하는 것입니다.

여러 개의 iframe 또는 팝업을 사용하여 여러 파일 다운로드를 시작할 수 있다고 가정하지만 사용성 관점에서 보면 ZIP 파일이 여전히 더 좋습니다. 누가 브라우저에 표시되는 10 개의 “다른 이름으로 저장”대화 상자를 클릭할까요?


답변

zip 파일이 더 깔끔한 솔루션이라는 데 동의합니다.하지만 여러 파일을 푸시해야하는 경우 여기에 제가 생각해 낸 솔루션이 있습니다. IE 9 이상 (아마도 더 낮은 버전도 테스트하지 않았 음), Firefox, Safari 및 Chrome에서 작동합니다. Chrome은 사이트에서 처음 사용할 때 여러 파일을 다운로드하는 데 동의한다는 메시지를 사용자에게 표시합니다.

function deleteIframe (iframe) {
    iframe.remove();
}
function createIFrame (fileURL) {
    var iframe = $('<iframe style="display:none"></iframe>');
    iframe[0].src= fileURL;
    $('body').append(iframe);
    timeout(deleteIframe, 60000, iframe);
 }
 // This function allows to pass parameters to the function in a timeout that are
 // frozen and that works in IE9
 function timeout(func, time) {
      var args = [];
      if (arguments.length >2) {
           args = Array.prototype.slice.call(arguments, 2);
      }
      return setTimeout(function(){ return func.apply(null, args); }, time);
 }
 // IE will process only the first one if we put no delay
 var wait = (isIE ? 1000 : 0);
 for (var i = 0; i < files.length; i++) {
      timeout(createIFrame, wait*i, files[i]);
 }

이 기술의 유일한 부작용은 제출과 다운로드 대화 상자 사이에 지연이 표시된다는 것입니다. 이 효과를 최소화하려면 여기 와이 질문에 설명 된 기술을 사용하는 것이 좋습니다. 브라우저가 다운로드를 시작 했음을 알 수 있도록 파일과 함께 쿠키를 설정하는 파일 다운로드수신 할 때 검색합니다 . 이 쿠키를 클라이언트 측에서 확인하고 서버 측으로 보내야합니다. 쿠키에 대한 적절한 경로를 설정하는 것을 잊지 마십시오. 그렇지 않으면 쿠키가 표시되지 않을 수 있습니다. 또한 여러 파일 다운로드를 위해 솔루션을 조정해야합니다.


답변

iframe의 jQuery 버전은 다음과 같이 대답합니다.

function download(files) {
    $.each(files, function(key, value) {
        $('<iframe></iframe>')
            .hide()
            .attr('src', value)
            .appendTo($('body'))
            .load(function() {
                var that = this;
                setTimeout(function() {
                    $(that).remove();
                }, 100);
            });
    });
}