Download per AJAX & Content Type 'application/force-download'

NetBull

Erfahrenes Mitglied
Hi,

ich hab mir ein kleines Script gebaut das in Artikeln eines CMS (Joomla) Download-Links zu Dateien ermöglicht die nicht im Pfad des Webservers liegen. So können diese nur angemeldete Benutzer sehen und downloaden.

Funktioniert hervorragend! Leider nur im Chrome Browser. FireFox meckert das Dokument sei nicht länger verwendbar.
Code:
InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
requestObject.responseType = 'blob';

Zum Code:
Dazu gibt es ein clickbares ICON das in dieser Art aufgebaut wird:
Code:
<img
    class="icon docx"
    onclick="loadDocument(this);"
    index="0"
    src="http://192.168.178.34/file-stream/word.png"
    alt="document"
    title="Das ist dann der Tooltip dazu"
>

Dann wird auf den Click mit diesen Funktionen reagiert:
Javascript:
function loadDocument(element){
    console.log("jQuery Version : " + jQuery.fn.jquery)
    console.log("Initiate document download request");
    var requestObject = getRequestObject();
    requestObject.responseType = 'blob';
    requestObject.open('GET', 'http://192.168.178.34/file-stream/response.php', true);          
    requestObject.onreadystatechange = function() {
        console.log("response readyState (" + requestObject.readyState + ") and status (" + requestObject.status + ")");
     
        if(requestObject.readyState == 4 && requestObject.status == 200) {
            console.log("Final Response has been taken!");
            if( requestObject.response.type!= "" ){
                console.log("Seems to be a valid download ressource!");
                var url = URL.createObjectURL(requestObject.response);                      
                var a = document.createElement('a');
               a.setAttribute('href', url);
               a.setAttribute('download', 'test.pdf');
               a.click();
               URL.revokeObjectURL(url);
               console.log("Download has been done!");
            } else {
                console.log("Seems to be an invalid download ressource!");
                console.log("Download gets aborted!");
            }
        }
    };
    requestObject.send();
}

function getRequestObject(){
    var returnObject;
    if (window.XMLHttpRequest)
    {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        console.log("initiate XMLHttpRequest");
        returnObject=new XMLHttpRequest();
    }
    else
    {
        // code for IE6, IE5
        console.log("initiate Microsoft.XMLHTTP request");
        returnObject=new ActiveXObject("Microsoft.XMLHTTP");
    }
    return returnObject;
}

Und hiermit wird von PHP ein Response generiert:
PHP:
$file_path = '/var/www/docs/bescheinigung.pdf';
$file_name = 'bescheinigung.pdf';

if( file_exists($file_path) ){
    header("Content-Type: application/force-download");
    header("Content-type: application/pdf");
    header('Content-Description: File Download');
    header('Content-Disposition: attachment; filename=' . $file_name);
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-length: ' . filesize($file_path));
    ob_clean();
    flush();
    readfile($file_path);
}

Wäre cool wenn mir jemand sagen kann wo mein Fehler ist.

LG NetBu||
 
Hallo NetBull

Du musst:
request = ...;
request.open(...)
request.responseType = 'blob';

Grund dafür ist - so vermute ich - das in Firefox die responseType-Eigenschaft nicht gesetzt werden kann, wenn der Request synchron ist, daher muss zuerst festgestellt werden ob synchron oder asynchron.

Grüsse
Cromon
 
Was ich nicht ganz verstehe, ist, warum Du jQuery verwendest, aber dann nicht die AJAX-API von jQuery.
Javascript:
function loadDocument( element ) {
  $.ajax( 'http://192.168.178.34/file-stream/response.php', {
    'xhrFields' : {
      'responseType' : 'blob'
    },
    'dataType' : 'binary'
  })
  .done(function ( data ) {
    var $a = $( '<a />' ), url = URL.createObjectURL( data );
    $a.attr({
      'href' : url,
      'download' : 'test.pdf'
    })
    .trigger( 'click' );
    URL.revokeObjectURL( url );
  });
}
 
Hi

versuch mal folgende zwei Zeilen zu tauschen, sodass du den responseType nach open setzt.
Javascript:
requestObject.open('GET', '/echo/html/', true); 
requestObject.responseType = 'blob';

Aber ich schliesse mich auch Cracks Frage an, wieso benutzt du nicht jQuerys AJAX Methode whenn du jQuery ja eh schon geladen hast.
 
Weil ich als nicht-jquery-Nutzer nach kurzem googeln zum Schluss kam, dass einen Blob via Ajax zu erhalten bei jQuery einen relativ grossen Aufwand bedeutet. Daher riet ich ihm gleich direkt mit dem zu Grunde liegenden Objekt zu arbeiten. Scheint offenbar dennoch einfach möglich zu sein.
 
Moin, weil....
weil:
Uncaught TypeError: Cannot read property 'ajax' of undefinedlink.html:61 loadDocumentlink.html:89 onclick
 
Es wäre schön, wenn wir jetzt noch wüssten, welche Zeilen das sind.

Nachtrag: Ich vermute, dass das Problem deshalb auftritt, weil jQuery nicht korrekt eingebunden wurde und dementsprechend die Variable $ nicht mit einer Instanz von jQuery belegt ist und somit auch die Funktion/Eigenschaft ajax nicht existiert. Somit kannst Du diesen Aufruf auch nicht nutzen.

Javascript:
var isJQuery = ( typeof( $ ) === 'function' && typeof( $.ajax ) === 'function' );
console.log( 'jQuery ist' + ( isJQuery ? ' ' :  'nicht ' ) + 'initialisiert.' );
 
Zuletzt bearbeitet:
@einfach nur crack ::

Moin,

hab das jQuery so eingebunden: Wie initialisiert man das? Hab das noch nie initialisieren müssen.

HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">

    <title>Insert title here</title>
    <script src="js/jquery.min.js" type="text/javascript"></script>
    <script src="js/jquery-noconflict.js" type="text/javascript"></script>
    <script src="js/jquery-migrate.min.js" type="text/javascript"></script>
    <script src="js/bootstrap.min.js" type="text/javascript"></script>
   
    <script type="text/javascript">
       
        function loadDocument( element ) {
            var isJQuery = ( typeof( $ ) === 'function' && typeof( $.ajax ) === 'function' );
            console.log( 'jQuery ist ' + ( isJQuery ? ' ' :  'nicht ' ) + 'initialisiert.' );
             $.ajax( 'http://192.168.178.34/file-stream/response.php', {
               'xhrFields' : {
                 'responseType' : 'blob'
               },
               'dataType' : 'binary'
             })
             .done(function ( data ) {
               var $a = $( '<a />' ), url = URL.createObjectURL( data );
               $a.attr({
                 'href' : url,
                 'download' : 'test.pdf'
               })
               .trigger( 'click' );
               URL.revokeObjectURL( url );
             });
            }
       
       
    </script>
</head>
<body>

<img 
    class="icon docx" 
    onclick="loadDocument(this);" 
    index="0" 
    src="/file-stream/word.png" 
    alt="document" 
    title="Das ist dann der Tooltip dazu"
>
   
<img 
    class="icon docx" 
    onclick="loadDocument(this);" 
    index="0" 
    src="/file-stream/pdf.png" 
    alt="document" 
    title="Das ist dann der Tooltip dazu">

</body>
</html>

LG NetBu||
 
oops peinlich... lol...


Code:
$ = jQuery;
        $( document ).ready(function() {
            $('.documentIcon').click(function(){
                console.log('clicked');
            });
        });

natürlich muss ich jetzt initialisieren.....
 
so hier mal das jQuery (diesmal initialisiert)
Code:
$ = jQuery;
        $( document ).ready(function() {
            $('.documentIcon').click(function(){
                var src = $(this).attr('src');
                $.ajax( 'http://192.168.178.34/file-stream/response.php', {
                    'xhrFields' : {
                        'responseType' : 'blob'
                    },
                    'dataType' : 'binary'
                })
                .done(function ( data ) {
                    var $a = $( '<a />' ), url = URL.createObjectURL( data );
                    $a.attr({
                        'href' : url,
                        'download' : 'test.pdf'
                    })
                    .trigger( 'click' );
                    URL.revokeObjectURL( url );
                });
            });
        });

Nur bekomme ich immer noch einen Fehler und habe keine Ahnung ....

Chrome sagt: Uncaught InvalidStateError: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'blob').jquery.min.js:4 b

FireFox sagt:
Javascript:
InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
   

...SON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,funct...
 

Neue Beiträge

Zurück