Preview Word, PowerPoint, Excel files and more file types

Thought I'd share how we're previewing files other than PDFs that the Knack viewer handles beautifully.  One of our apps is dependent on file records and users need quick access to preview without downloading.

Importantly there's no file conversion performed which is problematic especially for Office documents where tables and text boxes typically don't behave with conversions we tried with cloud services.  And Office documents get the benefit of the Microsoft Web Viewer menus and controls, including Excel table filters and Word accessibility features.

![](upload://zidPTtNlOrdqnlHiqbtgbmMvnCG.png)

Check it out here https://support.knack.com/hc/en-us/community/posts/360072660492 

Brad, re-iterating my comment for visibility:

Hey Brad! Nice work, and looks great. We went down that rabbit hole a little while ago with both those web viewers. We had it working for a brief week, but my intern at the time pointed out, specifically in reference to the main reply’s edit in this Stack Overflow article

using both google and Microsoft’s preview API’s WILL upload your files to a 3rd party server. Who knows what they plan to do with that data store. This proved to be completely unacceptable for our use case. As our files are invoices, client purchasing docs, govt docs, and other company sensitive data.

So we built our own tool in-house to handle it (with no 3rd party upload). Check it out here: 

Updated to use a much simpler approach - a warning, this replaces the hyperlink html entirely, and each file is opened in another tab.

$(document).on('knack-view-render.any', function (event, view, data) {
    setFileViewer();
});

function setFileViewer() {
    $('.kn-view-asset').each(function() {
        let arr = $(this).text().split('.')
        let extension = arr[arr.length - 1]
        let url = 'https://api.knack.com/v1/applications/' + Knack.app.id + '/download/asset/' + $(this).attr('data-asset-id') + '/' + $(this).attr('data-file-name');

        $(this).replaceWith('<a target="_blank" href="' + fileViewer(extension, url) + '">' + $(this).text() + '</a>');
    });
}

function fileViewer(e, url) {
    switch (e = e.toLowerCase()) {
        case "pdf":
        case "txt":
        case "html":
        case "jpg":
        case "jpeg":
        case "bmp":
        case "png":
        case "mpg":
        case "mpeg":
        case "wmv":
        case "mp4":
        case "dvr-ms":
        case "avi":
        case "mov":
        case "ogg":
        case "mkv":
            return url;
        case "docx":
        case "docm":
        case "doc":
        case "dotx":
        case "dotm":
        case "dot":
        case "xlsx":
        case "xls":
        case "ppts":
        case "ppt":
        case "pptx":
            return 'https://view.officeapps.live.com/op/view.aspx?src=' + url;
        default:
            return 'https://docs.google.com/gview?url=' + url;
    }
}
3 Likes

Hi @BradStevens

This is amazing thank you. We have been looking for something like this for quite a while.

Craig

Works really well. I don’t suppose you found any online viewer that works with .MSG files from Outlook? Or a way to invoke a local application (like Outlook) to view the file?

Hey @BradStevens. This is great. However since this does replace the URL, do you have a workaround to maintain the ability to download the file if needed? In my use case it is nice to be able to preview the file but on occasion the user will need to be able to download the file for purposes of emailing to a vendor, client, etc.

G’day @Nathan7 no I haven’t, from memory the Microsoft viewer includes a download link but the Google viewer doesn’t (I might be wrong). Using Javascript I’m sure the asset link could be duplicated to provide both options - i.e. view, or download.

Here’s what I came up with to solve that issue. Originally I had it set so that everything had a download link but that got a little cluttered on my view. So I modified it so that it kept the download link for anything other than the native viewer files.

I have this in a Grid view for documents associated with a record. I have inline editing enabled for the grid but I used the KTL to disable inline for the ‘File’ column. I had to do that because if I clicked on the download link, knack would just spin about while popping up the edit bubble to add a file. Once I disabled inline editing for that column it would download like expected.

$(document).on('knack-view-render.any', function (event, view, data) {
    setFileViewer();
});

function setFileViewer() {
    $('.kn-view-asset').each(function() {
        let arr = $(this).text().split('.');
        let extension = arr[arr.length - 1].toLowerCase();
        let fileName = $(this).attr('data-file-name'); // Get filename
        let fileId = $(this).attr('data-asset-id'); // Get file ID
        let fileUrl = 'https://api.knack.com/v1/applications/' + Knack.app.id + '/download/asset/' + fileId + '/' + fileName;

        // Get viewer URL
        let viewerUrl = fileViewer(extension, fileUrl);

        // Create viewer link
        let viewerLink = $('<a>')
            .attr('href', viewerUrl)
            .attr('target', '_blank')
            .text($(this).text());

        // Replace current text with viewer link
        $(this).replaceWith(viewerLink);

        // Append a download link if the file is an Office document or an unsupported file
        if (shouldShowDownloadLink(extension) || isOfficeFile(extension)) {
            let downloadLink = $('<a>')
                .attr('href', fileUrl)
                .attr('download', fileName)
                .text(' Download')
                .css({
                    'margin-left': '10px',
                    'color': 'blue',
                    'text-decoration': 'underline',
                    'cursor': 'pointer'
                });

            viewerLink.after(downloadLink);
        }
    });
}

// Function to determine if a download link should be shown for unsupported files
function shouldShowDownloadLink(extension) {
    let supportedExtensions = [
        "pdf", "txt", "html", "jpg", "jpeg", "bmp", "png",
        "mpg", "mpeg", "wmv", "mp4", "dvr-ms", "avi", "mov", "ogg", "mkv"
    ];
    return !supportedExtensions.includes(extension);
}

// Function to check if a file is an Office file (so we always show a download link)
function isOfficeFile(extension) {
    let officeExtensions = [
        "docx", "docm", "doc", "dotx", "dotm", "dot",
        "xlsx", "xlsm", "xls",
        "ppts", "ppt", "pptx"
    ];
    return officeExtensions.includes(extension);
}

// Function to determine viewer URL
function fileViewer(e, url) {
    switch (e) {
        case "pdf":
        case "txt":
        case "html":
        case "jpg":
        case "jpeg":
        case "bmp":
        case "png":
        case "mpg":
        case "mpeg":
        case "wmv":
        case "mp4":
        case "dvr-ms":
        case "avi":
        case "mov":
        case "ogg":
        case "mkv":
            return url;
        case "docx":
        case "docm":
        case "doc":
        case "dotx":
        case "dotm":
        case "dot":
        case "xlsx":
        case "xlsm":
        case "xls":
        case "ppts":
        case "ppt":
        case "pptx":
            return 'https://view.officeapps.live.com/op/view.aspx?src=' + url;
        default:
            return 'https://docs.google.com/gview?url=' + url;
    }
}
1 Like