Bookstack: [Feature Request] Preview for PDF Attachments

Created on 18 Feb 2018  Â·  11Comments  Â·  Source: BookStackApp/BookStack

Feature Request

Hey Everybody,
i am very happy to see the rapid progress about the App - great Work
But i miss the function, that I can get a preview of attached pdf-Files, before I downloading it.
It would be very nice, when these feature where implement in the next versions of Bookstack.

Feature Request

Most helpful comment

Created a more userfriendly version.

Code & Readme at: https://gist.github.com/albertmatyi/7c23a679a4a81c61c3628f6c15480b76

  1. Toolbar button
    2018-07-18-095853_235x88_scrot
  2. Popup dialog:
    2018-07-18-100325_590x429_scrot
  3. Edit mode PDF placeholder
    2018-07-18-100404_854x392_scrot
  4. Embedded PDF
    2018-07-18-100533_872x657_scrot

All 11 comments

@Yoginth
I think you got the question wrong. It is not about the generation of PDF-files.

@ITforHome
Can you please give some details on how the preview should look?

Currently the attachements are only downloaded. In case of PDF there are severall possibilities to implement a "preview". There can be a real preview in form of a generated image including only the first page of the pdf, change the 'Content-Type' for this download (as suggested by @Yoginth) so the browser uses the defined preview(plugin) or embedd a preview using pdfjs or something. In the last 2 cases the file technically is already downloaded to your computer.

@Yoginth yes and no.
File attachments are handled by AttachmentController.php (not by the PageController) and Downloads by the get-method. If you change the Content-Type for all filetypes this will most likely result in errors when you attach and later download a zip, exe, ... file.

@Yoginth
i have changed the Content-Type to 'Content-Type' => 'application/octet-stream' in the PageController.php file, but is not working. When i click on an attached pdf-File, i can only downloaded it, but i can't get a preview.

@lommes
i have changed the Content-Txpe to 'Content-Type' => 'application/pdf' in the AttachmentController.php file, but is not working too. When i also click on an attached pdf-File, i can only downloaded it, no preview.

General:
In my question i mean any attached pdf-File NO the generated PDF-File of a page in Bookstack

When I open the Bookstack App on Mobile Safari or Chrome I get a preview about attached PDF-Files when I click on it.

I've created a small hack (quick solution for own deployment) to be able to view pdf attachments as embedded documents in a page.

"Installation"

Add the following script to the CUSTOM HTML HEAD content on the Settings pane.
2018-07-11-102632_835x87_scrot

    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.0.466/pdf.min.js"></script>
<style>
canvas[data-pdfurl] {
  background-color: lightgrey;
   width: 100%;
}
.page-content a {
 color: #39f;
text-decoration: underline;
}
.pdf-wrapper {
position: relative;
height: 80vh;
width: 100%;
}
.pdf-wrapper .download-link {
position: absolute;
top: -2em; 
right: 0;
z-index: 50;
}
.pdf-wrapper .pdf-scroller {
height: 100%;
overflow: auto;
}
</style>
<script type="text/javascript">
window.addEventListener('load', function () {
var renderPdf=function(canvas) {
  var url = canvas.dataset.pdfurl;
  var pdf = null;
  // wrap canvas in div
  var wrapper = document.createElement('div');
  wrapper.className='pdf-wrapper';
  var scroller = document.createElement('div');
  scroller.className='pdf-scroller';
  wrapper.appendChild(scroller);
  canvas.parentNode.insertBefore(wrapper, canvas.nextSibling);
  scroller.insertBefore(canvas, null);

  var downloadLink  = document.createElement('a');
  downloadLink.href = url;
  downloadLink.className="download-link";
  downloadLink.innerText = 'Download PDF now ↓';
  wrapper.appendChild(downloadLink);

  var renderPage = function(page) {
    var scale = 1.5;
    var viewport = page.getViewport(scale);
    // Fetch canvas' 2d context
    var context = canvas.getContext('2d');
    // Set dimensions to Canvas
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    canvas.style.maxWidth='100%';
    // Prepare object needed by render method
    var renderContext = {
      canvasContext: context,
      viewport: viewport
    };
    // Render PDF page
    page.render(renderContext);
    if (currentPage < pdf.numPages) {
      currentPage++;
      var newCanvas = document.createElement('canvas');
      scroller.insertBefore(newCanvas, canvas.nextSibling);
      scroller.insertBefore(document.createElement('hr'), canvas.nextSibling);
      canvas=newCanvas;
      pdf.getPage(currentPage).then(renderPage);
    }
  };
  var currentPage = 1;
  pdfjsLib.getDocument(url)
  .then(function(pdfLocal) {
    pdf = pdfLocal;
    return pdf.getPage(1);
  })
  .then(renderPage);
}
Array.prototype.forEach.call(
  document.querySelectorAll('canvas[data-pdfurl]'),
  renderPdf);
});
</script>

Usage

  1. Attach pdf to the page
  2. In the source editing mode insert the line:
    <p>&nbsp;<canvas data-pdfurl="https://wiki.justrocket.de/attachments/3"></canvas>&nbsp;</p>
    where 3 is the id of the attachment (hover the attachment link to see the number)

@albertmatyi your solution works great! thank you!

Created a more userfriendly version.

Code & Readme at: https://gist.github.com/albertmatyi/7c23a679a4a81c61c3628f6c15480b76

  1. Toolbar button
    2018-07-18-095853_235x88_scrot
  2. Popup dialog:
    2018-07-18-100325_590x429_scrot
  3. Edit mode PDF placeholder
    2018-07-18-100404_854x392_scrot
  4. Embedded PDF
    2018-07-18-100533_872x657_scrot

For anyone coming across this and wanting to view PDF attachments in the browser, change the return statement of app/Http/Controllers/AttachmentController.php to this:

    $contentType = 'application/octet-stream';
    $contentDisposition = 'attachment';

    if ($attachment->extension === "pdf") {
            $contentType = 'application/pdf';
            $contentDisposition = 'inline';
    }

    return response($attachmentContents, 200, [
        'Content-Type' => $contentType,
        'Content-Disposition' => $contentDisposition.'; filename="'. $attachment->getFileName() .'"'
    ]);

For anyone coming across this and wanting to view PDF attachments in the browser, change the return statement of app/Http/Controllers/AttachmentController.php to this:

    $contentType = 'application/octet-stream';
    $contentDisposition = 'attachment';

    if ($attachment->extension === "pdf") {
            $contentType = 'application/pdf';
            $contentDisposition = 'inline';
    }

    return response($attachmentContents, 200, [
        'Content-Type' => $contentType,
        'Content-Disposition' => $contentDisposition.'; filename="'. $attachment->getFileName() .'"'
    ]);

Where? There are a lot of functions in that file.
P.S. Not a php developer so excuse my stupidity.

@aldoblack I think it's intended to be a replacement of this line:
https://github.com/BookStackApp/BookStack/blob/v0.28.3/app/Http/Controllers/AttachmentController.php#L198

Note, Such changes to core files are not officially supported and may cause complications, or be lost, when you upgrade.

@aldoblack I think it's intended to be a replacement of this line:
https://github.com/BookStackApp/BookStack/blob/v0.28.3/app/Http/Controllers/AttachmentController.php#L198

Note, Such changes to core files are not officially supported and may cause complications, or be lost, when you upgrade.

I understand. Thank You very much.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Wookbert picture Wookbert  Â·  3Comments

alex2702 picture alex2702  Â·  3Comments

davidtessier picture davidtessier  Â·  3Comments

Valiantiam picture Valiantiam  Â·  3Comments

Legoracers picture Legoracers  Â·  3Comments