Najłatwiejszy sposób na otwarcie okna pobierania bez opuszczania strony

119

Jaki jest najlepszy sposób otwierania okna pobierania w różnych przeglądarkach (załóżmy, że możemy ustawić dyspozycję zawartości: załącznik w nagłówkach) bez konieczności opuszczania bieżącej strony lub otwierania wyskakujących okienek, co nie działa dobrze w przeglądarce Internet Explorer (IE ) 6.

mkoryak
źródło

Odpowiedzi:

106

Minęło 7 lat i nie wiem, czy działa z IE6, czy nie, ale to podpowiada OpenFileDialog w FF i Chrome.

var file_path = 'host/path/file.ext';
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
0x000f
źródło
Najpierw dziękuję za to rozwiązanie, ale znalazłem błąd, jeśli removeChild (a) zip rozpakuje błąd z zipem jest uszkodzony, więc usuń ten kod, rozwiąż go
Roy
2
@Manoj Rana - Sprawdziłem na FF 58.0.2 (64-bit) działa. Nie zadziała na żadnym FF, jeśli usuniesz 2 linie document.body.appendChild (a); document.body.removeChild (a);
0x000f
1
Aby działało na Edge 16, nagłówek, z którego pochodzi plik, powinien zawierać Content-Type: application/octet-streami Content-Disposition: attachment.
Simon
12
to już nie działa developers.google.com/web/updates/2018/02/…
Paulius Dragunas
2
@ user1933131 chrome usuwa tylko dla cross-origin
Brandy23
202

Ten javascript jest fajny, że nie otwiera nowego okna ani karty.

window.location.assign(url);
mozgras
źródło
18
To jest to samo, co window.location = url; „Za każdym razem, gdy obiektowi lokalizacji przypisywana jest nowa wartość, dokument zostanie załadowany przy użyciu adresu URL, tak jakby wywołano window.location. assign () ze zmodyfikowanym adresem URL” - developer.mozilla.org/en-US/docs/ Web / API / window.location
Rob Juurlink
13
Powoduje to rozłączenie połączenia WebSocket.
igorpavlov
4
Użyłem tego samego rozwiązania, ale otwiera plik na tej samej karcie zamiast otwierania okna dialogowego pobierania.
Techno Cracker
2
to samo dotyczy window.open (url, '_self'), jeśli adres URL jest przeznaczony do pobrania strony.
Ekspert chce być
5
Podczas korzystania z IE11 stwierdziłem, że spowodowało to zatrzymanie JS. Więc dla IE 11 użyłem window.open (url, '_blank'), który otworzył kolejną kartę, jednak ta karta została zamknięta, gdy się okazało, że plik był do pobrania. To utrzymało działanie JS.
Łukasz
23

Zawsze dodaję target = "_ blank" do linku pobierania. Otworzy się nowe okno, ale gdy tylko użytkownik kliknie przycisk Zapisz, nowe okno zostanie zamknięte.

jao
źródło
2
To najlepsza odpowiedź. W przeglądarce Internet Explorer dodanie „target =" _ blank "” do łącza, które ma zostać pobrane, zatrzyma przeglądarkę przed opuszczeniem jej (tam, gdzie jest drukowane „HTML1300: Nawigacja wystąpiła”), a tym samym może pozostawić stronę w niespójnym stanie.
user64141
23

Umieść to w sekcji nagłówka HTML, ustawiając urlzmienną na adres URL pliku do pobrania:

<script type="text/javascript">  
function startDownload()  
{  
     var url='http://server/folder/file.ext';    
     window.open(url, 'Download');  
}  
</script>

Następnie umieść to w treści, która rozpocznie pobieranie automatycznie po 5 sekundach:

<script type="text/javascript">  
setTimeout('startDownload()', 5000); //starts download after 5 seconds  
</script> 

( Stąd .)

George Claghorn
źródło
2
to nie działa, ponieważ w IE6, jeśli użytkownik kliknie „zapisz”, plik zostanie zapisany, ale wyskakujące okienko pozostanie otwarte. To nie jest do zaakceptowania.
mkoryak
ten kod nie działa w safari, czy możesz mi pomóc rozwiązać w safari, proszę.
Renish Khunt
17

Wiem, że zadano pytanie, 7 years and 9 months agoale wiele opublikowanych rozwiązań wydaje się nie działać, na przykład używanie <iframe>tylko działa z, FireFoxa nie działa Chrome.

Najlepsze rozwiązanie:

Najlepszym działającym rozwiązaniem do otwierania wyskakującego okienka pobierania pliku JavaScriptjest użycie HTMLelementu link, bez konieczności dołączania elementu link do elementu,document.body jak podano w innych odpowiedziach.

Możesz użyć następującej funkcji:

function downloadFile(filePath){
    var link=document.createElement('a');
    link.href = filePath;
    link.download = filePath.substr(filePath.lastIndexOf('/') + 1);
    link.click();
}

W mojej aplikacji używam go w ten sposób:

downloadFile('report/xls/myCustomReport.xlsx');

Działające demo:

Uwaga:

  • Musisz użyć link.downloadatrybutu, aby przeglądarka nie otworzyła pliku w nowej karcie i uruchomiła wyskakujące okienko pobierania.
  • Zostało to przetestowane z kilkoma typami plików (docx, xlsx, png, pdf, ...).
cнŝdk
źródło
Jaki byłby najlepszy sposób na wyświetlenie ładującego się gifa przed pobraniem pliku?
Ctrl_Alt_Defeat
1
@Ctrl_Alt_Defeat Cóż, w tym przypadku nie będzie łatwo śledzić proces pobierania, ale jedną sztuczką może być pokazanie tej animacji gif po linkkliknięciu i ukrycie jej po pewnym czasie za pomocą tego kodu: link.onclick = function() { document.body.innerText = "The file is being downloaded ..."; setTimeout(function() { document.body.innerText = ""; }, 2000); }możesz zobaczyć, jak działa w tym skrzypce , ale pamiętaj, że nie jest to zalecany sposób robienia tego, byłoby lepiej, gdybyśmy używali Ajax.
cнŝdk
1
to nie działa w przeglądarce Firefox. jak pobrać w przeglądarce Firefox?
Manoj Rana
@ManojRana W przypadku przeglądarki Firefox możesz użyć opcji iframezobacz tę odpowiedź .
cнŝdk
2
To rozwiązanie działa u mnie w Chrome, Safari i Firefox :)
ariebear
15

Szukałem dobrego sposobu na użycie javascript do zainicjowania pobierania pliku, tak jak sugeruje to pytanie. Jednak te odpowiedzi nie były pomocne. Następnie przeprowadziłem kilka testów xbrowser i odkryłem, że iframe działa najlepiej we wszystkich nowoczesnych przeglądarkach IE> 8.

downloadUrl = "http://example.com/download/file.zip";
var downloadFrame = document.createElement("iframe"); 
downloadFrame.setAttribute('src',downloadUrl);
downloadFrame.setAttribute('class',"screenReaderText"); 
document.body.appendChild(downloadFrame); 

class="screenReaderText" to moja klasa do stylizowania zawartości, która jest obecna, ale nie można jej wyświetlić.

css:

.screenReaderText { 
  border: 0; 
  clip: rect(0 0 0 0); 
  height: 1px; 
  margin: -1px; 
  overflow: hidden; 
  padding: 0; 
  position: absolute; 
  width: 1px; 
}

tak samo jak .visuallyHidden w html5boilerplate

Wolę to od metody window.open w javascript, ponieważ jeśli łącze jest zepsute, metoda iframe po prostu nie robi nic, w przeciwieństwie do przekierowywania na pustą stronę z informacją, że nie można otworzyć pliku.

window.open(downloadUrl, 'download_window', 'toolbar=0,location=no,directories=0,status=0,scrollbars=0,resizeable=0,width=1,height=1,top=0,left=0');
window.focus();
alockwood05
źródło
6

Korzystanie z interfejsu API pliku HTML5 Blob Object-URL File:

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
*/
var saveBlobAsFile = function(fileName,fileContents) {
    if(typeof(Blob)!='undefined') { // using Blob
        var textFileAsBlob = new Blob([fileContents], { type: 'text/plain' });
        var downloadLink = document.createElement("a");
        downloadLink.download = fileName;
        if (window.webkitURL != null) {
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        }
        else {
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            downloadLink.onclick = document.body.removeChild(event.target);
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        downloadLink.click();
    } else {
        var pp = document.createElement('a');
        pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
        pp.setAttribute('download', fileName);
        pp.onclick = document.body.removeChild(event.target);
        pp.click();
    }
}//saveBlobAsFile

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
 */
var saveBlobAsFile = function(fileName, fileContents) {
  if (typeof(Blob) != 'undefined') { // using Blob
    var textFileAsBlob = new Blob([fileContents], {
      type: 'text/plain'
    });
    var downloadLink = document.createElement("a");
    downloadLink.download = fileName;
    if (window.webkitURL != null) {
      downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    } else {
      downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
      downloadLink.onclick = document.body.removeChild(event.target);
      downloadLink.style.display = "none";
      document.body.appendChild(downloadLink);
    }
    downloadLink.click();
  } else {
    var pp = document.createElement('a');
    pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
    pp.setAttribute('download', fileName);
    pp.onclick = document.body.removeChild(event.target);
    pp.click();
  }
} //saveBlobAsFile

var jsonObject = {
  "name": "John",
  "age": 31,
  "city": "New York"
};
var fileContents = JSON.stringify(jsonObject, null, 2);
var fileName = "data.json";

saveBlobAsFile(fileName, fileContents)

loretoparisi
źródło
2
Czuję, że to najlepszy sposób na zrobienie tego !!
Kushal MK
1
Dobrą praktyką jest również dzwonienie URL.revokeObjectURL(url), gdy plik nie jest już potrzebny do zwolnienia pamięci
SleepWalker
5

Modyfikacja lokalizacji okna może spowodować pewien problem, szczególnie w przypadku trwałego połączenia, takiego jak websocket. Dlatego zawsze uciekam się do starego, dobrego rozwiązania iframe.

HTML

<input type="button" onclick="downloadButtonClicked()" value="Download"/>
...
...
...
<iframe style="display:none;" name="hiddenIframe" id="hiddenIframe"></iframe>

Javascript

function downloadButtonClicked() {
    // Simulate a link click
    var url = 'your_download_url_here';
    var elem = document.createElement('a');
    elem.href = url;
    elem.target = 'hiddenIframe';
    elem.click();
}
Bnrdo
źródło
5

Jeśli łącze prowadzi do prawidłowego adresu URL pliku, wystarczy przypisać właściwość window.location.href.

Jednak czasami łącze jest nieprawidłowe i wymagany jest element iFrame.

Wykonaj swoje normalne event.preventDefault, aby zapobiec otwarciu okna, a jeśli używasz jQuery, zadziała:

$('<iframe>').attr('src', downloadThing.attr('href')).appendTo('body').on("load", function() {
   $(this).remove();
});
TaylorMac
źródło
2

Po godzinach prób narodziła się funkcja :) Miałem scenariusz, w którym musiałem wyświetlić loader w czasie, gdy plik jest przygotowywany do pobrania:

Działa w Chrome, Safari i Firefox

function ajaxDownload(url, filename = 'file', method = 'get', data = {}, callbackSuccess = () => {}, callbackFail = () => {}) {
    $.ajax({
        url: url,
        method: 'GET',
        xhrFields: {
            responseType: 'blob'
        },
        success: function (data) {
            // create link element
            let a = document.createElement('a'), 
                url = window.URL.createObjectURL(data);

            // initialize 
            a.href = url;
            a.download = filename;

            // append element to the body, 
            // a must, due to Firefox
            document.body.appendChild(a);

            // trigger download
            a.click();

            // delay a bit deletion of the element
            setTimeout(function(){
                window.URL.revokeObjectURL(url);
                document.body.removeChild(a);
            }, 100);

            // invoke callback if any 
            callbackSuccess(data);
        },
        error: function (err) {
            // invoke fail callback if any
            callbackFail(err)
        }
    });
М.Б.
źródło
0

Co powiesz na:

<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">

W ten sposób działa we wszystkich przeglądarkach (tak mi się wydaje) i pozwala umieścić komunikat typu: „Jeśli pobieranie nie rozpocznie się za pięć sekund, kliknij tutaj”.

Jeśli potrzebujesz javascript ... cóż ...

document.write('<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">');

pozdrowienia


źródło
0

W tym celu może działać mała / ukryta ramka iframe.

Dzięki temu nie musisz się martwić o zamknięcie wyskakującego okienka.

Szymon
źródło