2016-08-15 55 views
8

Musi istnieć sposób, aby zrobić to bardziej efektywnie. To, co robię, jest konceptualnie bardzo proste:IE i javascript: skuteczny sposób dekodowania (i renderowania) blobu PDF zakodowanego w formacie B64

1) Zadzwoń do serwisu internetowego i otrzymaj ciąg znaków zakodowany w formacie b64 bloku blob PDF.
2) Rozkoduj go, utwórz obiekt typu blob, wyrenderuj plik PDF w nowym oknie. Konto dla blokowania wyskakujących okienek.

Mój kod działa. Nic fajnego. To wszystko po stronie klienta. Wszystko działa, ale IE działa SUPER wolno w porównaniu do innych przeglądarek (IE 11 vs. aktualny Chrome/Firefox/Safari).

W świetle tego jestem pewien, że mogę to zrobić bardziej efektywnie. Wszelkie wskazówki, jak przyspieszyć ten proces w IE 11?

Uwaga: Używam funkcji Jeremy'ego b64toBlob (dzięki Jeremy).

Część I: modalna rzeczy

var box = new SimpleDialog(Dialogs.getNextId(), false); 
box.title = "Fetching PDF"; 
box.isMovable = false; 
box.extraClass = ""; 
box.width = 400; 
box.isModal = true; 
box.createDialog(); 
window.parent.box = box; 
box.setContentInnerHTML('<p>Please wait....</p>'); 
box.show(); 

Część II: zadzwoń usług zewnętrznych, otrzymują B64 zakodowany ciąg

setTimeout(function(){ 
    var response = ... ; //do callout... get data 
    var statusCode = ...; //parse from response 
    var b64Data = ... ; //parse from response 

    if(statusCode == 200) { 
    //Account for IE 
    if (navigator.appVersion.toString().indexOf('.NET') > 0) { 
     var blob = b64toBlob(b64Data, "application/pdf"); 
     var fileURL = URL.createObjectURL(blob); 
     window.navigator.msSaveOrOpenBlob(blob, "theFile.pdf"); 
     window.parent.box.cancel(); 
    } else { 
     var blob = b64toBlob(b64Data, "application/pdf"); 
     var fileURL = URL.createObjectURL(blob); 
     var pdfWin = window.open(fileURL,"_blank","width=1000,height=800"); 
     if(!pdfWin) { 
     box.setTitle("Success: PDF has been retrieved"); 
     box.setContentInnerHTML("<p align='left'></p><p align='left'>A popup blocker was detected. The PDF will not open automatically.<br /><br /></p><p align='left'><a onclick='window.parent.box.cancel();' target='_blank' href='"+fileURL +"' >Click here to view .pdf</a><br /><br /></p><p align='center'><button class='btn' onclick='window.parent.box.cancel(); return false;'>Cancel</button></p>"); 
     } else { 
     window.parent.box.cancel(); 
     } 
    } 

    } else { 
     box.setTitle("Error fetching PDF"); 
     box.setContentInnerHTML("<p align='left'><img src='/img/msg_icons/warning32.png' style='margin:0 5px;'/></p><p align='left'>Unable to retrieve PDF.</p><p align='center'><button class='btn' onclick='window.parent.box.cancel(); return false;'>OK</button></p>"); 
    } 
},200); 
+0

Gdybym musiał zgadnąć, powiedziałbym, że powodem, dla którego IE trwa tak długo, jest to, że metoda msSaveOrOpenBlob musi zapisać plik lokalnie. – QuestionMarks

+0

hmm. czy mówisz, że msSaveOrOpenBlob zapisuje lokalnie, zanim jeszcze wykona dialog zapisywania lub otwierania? – DasUberDanger

+1

Czy rozważałeś użycie webworkerów? Jeśli nie potrzebujesz obsługi wersji user2977636

Odpowiedz

2

ja naprawdę nie widzę żadnych powolność, a to plunkr uruchamiany w IE, (przy użyciu aktualizacji oryginalnego rozwiązania "Jeremy") działa dobrze:

Sample pdf

Wystąpił zmiana w oryginalnym poście, który poprawia odpowiedź dalej:

function base64toBlob(base64Data, contentType, sliceSize) { 

    var byteCharacters, 
     byteArray, 
     byteNumbers, 
     blobData, 
     blob; 

    contentType = contentType || ''; 

    byteCharacters = atob(base64Data); 

    // Get blob data sliced or not 
    blobData = sliceSize ? getBlobDataSliced() : getBlobDataAtOnce(); 

    blob = new Blob(blobData, { type: contentType }); 

    return blob; 


    /* 
    * Get blob data in one slice. 
    * => Fast in IE on new Blob(...) 
    */ 
    function getBlobDataAtOnce() { 
     byteNumbers = new Array(byteCharacters.length); 

     for (var i = 0; i < byteCharacters.length; i++) { 
      byteNumbers[i] = byteCharacters.charCodeAt(i); 
     } 

     byteArray = new Uint8Array(byteNumbers); 

     return [byteArray]; 
    } 

    /* 
    * Get blob data in multiple slices. 
    * => Slow in IE on new Blob(...) 
    */ 
    function getBlobDataSliced() { 

     var slice, 
      byteArrays = []; 

     for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { 
      slice = byteCharacters.slice(offset, offset + sliceSize); 

      byteNumbers = new Array(slice.length); 

      for (var i = 0; i < slice.length; i++) { 
       byteNumbers[i] = slice.charCodeAt(i); 
      } 

      byteArray = new Uint8Array(byteNumbers); 

      // Add slice 
      byteArrays.push(byteArray); 
     } 

     return byteArrays; 
    } 
} 

Od odpowiedź tutaj:

martinoss answer

jest plunkr powolne dla Ciebie? Czy możesz wprowadzić rejestrowanie, aby zrozumieć, które połączenie jest rzeczywiście wolne? Wstaw zegar i zapisz każdą linię. na trasie IE. Który z nich zgłasza "spowolnienie"?

Aktualizacja Na plunkr umieściłem bardzo prosty zegar, który pokazuje, że w IE11 zostało pobranych zaledwie 46 ms. Oczywiście nie jest wielowątkowy, ale jest to wskazanie.

+0

dzięki za wskazanie poprawionej metody "one slice" getBlobDataAtOnce(). To na pewno ogoli trochę czasu. – DasUberDanger