Follow

Displaying .rtf files in the browser

Introduction

The main aim of this blog is to show the content of an .rtf file on the browser window. Usually, when trying to open an .rtf file in the browser, it is downloaded instead of being displayed. This is because the browsers cannot reliably display RTF content. In order to overcome this problem, we came up with a solution which involves converting the contents of an .rtf file into HTML and then rendering it on the browser window.

This solution has no bearing on the server side programming language that is used. It is handled completely on the browser side.

Implementation

Assume that the file is hosted on a server which can be then retrieved via an AJAX call.

Step – 1
Upon making an ajax call to the server to retrieve the .rtf file, a blob will be received as shown in the image below –

Ajax call for .rtf

The in-built JavaScript FileReader object helps in reading the content of a blob. Below is the code snippet explaining how the content of the file is handled.

var reader = new FileReader();
reader.readAsArrayBuffer(result);

reader.onload = function (evt) {
  displayRtfFile(evt.target.result);
 };

You can read more about the FileReader object here. It is supported in most major browsers.

The FileReader object lets web applications asynchronously read the contents of the files. It provides various event handlers and methods. One of them is FileReader.onload.

In order to manipulate the content of the RTF file, the external library that we’re going to use requires the content to be an ArrayBuffer. This can be done by calling the FileReader‘s reader.readAsArrayBuffer() method.

So, after manipulating the file content using FileReader, the value that gets returned is as shown below –

rtf content

Take a look at the code snippet which does the above-explained work.

function (file) {
  $.ajax({
    url: file,
    dataType: "binary",
    processData: false,
    beforesend: function () {
      return true;
    },
    success: function (result) {
      // On success, we are getting the content of .rtf file as an ArrayBuffer using FileReader() function.
      var reader = new FileReader();
      reader.onload = function (evt) {
        // TODO: will be called after step #2
        // displayRtfFile(evt.target.result);
      };
      reader.readAsArrayBuffer(result);
    },
    error: function (jqXHR, textStatus, errorThrown) {
      $("#content").text("Error: " + errorThrown);
    }
  });
}
loadRtfFile(FILE_LOCATION)

Step – 2
Upon receiving the ArrayBuffer, a library called RTF.js is used that converts the buffered content into the HTML content that we want.

For proper handling of the content in the .rtf rile, settings can be provided as well. To customize the way images are shown in the rendered HTML file, we can provide these options in callbacks provided by the library.

Picture related settings

onPicture: function (create) {
  var elem = create().attr("class", "rtfpict"); 
  return elem.css("border", show ? "1px dotted red" : "none");
}

For example, using the onPicture property, a border can be added to the images that are present in the .rtf file and display them on the browser window.

Hyperlink related settings

We have the onHyperlink property to add custom styles/events to hyperlinks in the PDF.

onHyperlink:function (create, hyperlink) {
  var url = hyperlink.url();
  var lnk = create();
  if (url.substr(0, 7) == "http://") {
    var span = setUnsafeLink($("<span>").addClass("unsafelink").append(lnk), warnHttpLinks);
    span.click(function (evt) {
      if ($("#warnhttplink").prop("checked")) {
        evt.preventDefault();
        alert("Unsafe link: " + url);
        return false;
      }
    });
    return {
      content: lnk,
      element: span
    };
  } else {
    return {
      content: lnk,
      element: lnk
    };
  }
}

Below is the code snippet that takes an ArrayBuffer as input and returns an object comprising of meta data and the actual .rtf content.

function displayRtfFile(arrayBuffer) {
  var settings = {
    onPicture: function (create) {
      var elem = create().attr("class", "rtfpict");
      return elem.css("border", showPicBorder ? "1px dotted red" : "none");      
    },
    onHyperlink: function (create, hyperlink) {
      var url = hyperlink.url();
      var lnk = create();
      if (url.substr(0, 7) == "http://") {
        var span = setUnsafeLink($("<span>").addClass("unsafelink").append(lnk), warnHttpLinks);
        span.click(function (evt) {
          if ($("#warnhttplink").prop("checked")) {
            evt.preventDefault();
            alert("Unsafe link: " + url);
            return false;
          }
        });
        return {
          content: lnk,
          element: span
        };
      } else {
        return {
          content: lnk,
          element: lnk
        };
      }
    }
  };
  
  var doc = new RTFJS.Document(arrayBuffer, settings);
  var meta = doc.metadata();
  
  // Appending the meta information like - author of the document,
  // title of the of the document- into meta tag of html.
  
  for (var prop in meta) {
    $("meta").append($("<div>").append($("<span>").text(prop + ": "))
      .append($("<span>").text(meta[prop].toString())));
    haveMeta = true;
  }
  
  // Appending the content to html page.
  $("#content").empty().append(doc.render());
}

// Helper function to set border for unsafe links.
function setUnsafeLink(elem, warn) {
  return elem.css("border", warn ? "1px dashed red" : "none");
}

Metadata comprises of author name, file name, and description. This can be appended to the <meta></meta> tags of the HTML content.

Likewise, the actual content of the file is obtained by using the render() method of the included library.

Then, the rendered HTML content can be shown on the browser window by appending it to any element.

Posted BySai Manohar, Osmosee

Are you interested? follow us and get notified of new posts

Leave A Reply

18 + fourteen =