How to read PDF creation & modification date in NodeJS


You have a PDF file from which you want to know the creation and modification date: Not the dates stored in the file itself but those from the PDF metadata.


This solution assumes you use NodeJS version 8+ which supports async/await.
You can use pdfjs to read these dates. First install it using

npm install pdfjs-dist

Then use this code to extract the dates.

const pdfjs = require('pdfjs-dist');

async function readPDFDates() {
  const pdf = await pdfjs.getDocument('mypdf.pdf');
  const metadata = await pdf.getMetadata();

  const modDate = new Date(metadata.metadata._metadata['xmp:modifydate']);
  const createDate = new Date(metadata.metadata._metadata['xmp:createdate']);
  return [modDate, createDate]

readPDFDates().then(([modDate, createDate]) => {
    console.log(`Creation date: ${createDate}`)
    console.log(`Modification date: ${modDate}`)
}).catch(err => {
    console.error(`Error while reading PDF: ${err}`)


The PDF files I’ve seen use ISO8601-style formatting, but without a timezone specification. The code therefore assumes that the times are in the local timezone.

Note: metadata is e.g. the following object (not all attributes are present for all PDFs):

{ info: 
   { PDFFormatVersion: '1.5',
     IsAcroFormPresent: false,
     IsXFAPresent: false,
     Title: 'Microsoft Word - mypdf',
     Author: 'uli',
     Creator: 'PScript5.dll Version 5.2.2',
     Producer: 'Acrobat Distiller 9.3.0 (Windows)',
     CreationDate: 'D:20100209100924+01\'00\'',
     ModDate: 'D:20100209100924+01\'00\'' },
   Metadata {
      { 'dc:format': 'application/pdf',
        'dc:creator': 'peter',
        'dc:title': 'Microsoft Word - mypdf',
        'xmp:createdate': '2010-02-09T10:09:24+01:00',
        'xmp:creatortool': 'PScript5.dll Version 5.2.2',
        'xmp:modifydate': '2010-02-09T10:09:24+01:00',
        'pdf:producer': 'Acrobat Distiller 9.3.0 (Windows)',
        'xmpmm:documentid': 'uuid:2fd66f45-5f2a-4dd6-8cb0-297ce85ee9e1',
        'xmpmm:instanceid': 'uuid:f6e62218-4b40-47c7-837b-6cb1e6e90995' } },


How to add JS Drag-&-Drop file upload without any dependencies


For your new web application, you want to add drag&drop file uploads without using any external library.


You can use this set of functions, which you can adapt to your application.

 * Initialize drag & drop event handling for a DOM element.
 * The DOM element does not have to be empty in order to do this.
 * @param elem The DOM element where files can be dragged & dropped
 * @param callback The callback(files) function that gets passed a list of files
 * when files are dragged and dropped.
 * Basic usage example:
 *  var elem = document.getElementById('mydiv');
 *  initializeDragAndDrop(elem, function(files) {
 *      for (var i = 0; i < files.length; i++) {
 *          // Do something with files[i]...
 *          handleUploadedFile(files[i]); // Replace by your code
 *      }
 *  });
function initializeDragAndDrop (elem, callback) {
    elem.addEventListener('drop', function (event) {
    }, false);
    elem.addEventListener('dragover', _dragndrop_preventDefault, false);
    elem.addEventListener('dragdrop', _dragndrop_preventDefault, false);
    elem.addEventListener('dragenter', _dragndrop_preventDefault, false);
    elem.addEventListener('dragleave', _dragndrop_preventDefault, false);

 * Internal utility function to prevent default
 * handling for a given event.
function _dragndrop_preventDefault (event) {

Usage example:

var elem = document.getElementById('mydiv');
initializeDragAndDrop(elem, function(files) {
    for (var i = 0; i < files.length; i++) {
        // Do something with files[i]...
        handleUploadedFile(files[i]); // Replace by your code

Note that you need to run initializeDragAndDrop only after the respective DOM element (mydiv in this example) has been loaded. For example, you could call it like this if you use jQuery:

$(document).ready(function() {
    initializeDragAndDrop(/* ... */);

Pure Javascript (no jQuery):

// WARNING: This will replace any window.onload function
// that is currently set.
// Also, this will only fire after everything on the page
// has been loaded, which might not be the desired behaviour.
window.onload = function() {
    initializeDragAndDrop(/* ... */);

Also see this previous TechOverflow post on how to read the uploaded files into memory, if you need to.

Reading an uploaded file into memory using pure Javascript

You have a File object in Javascript (e.g. from a drag & drop upload or a <input type="file">) which you want to read into memory in the browser. You don’t want to use any library to do that but prefer a pure Javascript solution.


Use this function:

 * Utility function to read an entire file into memory.
 * The handler function gets passed an array of objects:
 * {
 *     name: filename as string,
 *     size: size in bytes as number,
 *     type: MIME type as string,
 *     content: file content as Uint8Array
 * }
 * @param file The file to read
 * @param handler
function readFileIntoMemory (file, callback) {
    var reader = new FileReader();
    reader.onload = function () {
            size: file.size,
            type: file.type,
            content: new Uint8Array(this.result)

Usage example:

// Usage example
readFileIntoMemory(file, function(fileInfo) {"Read file " + + " of size " + fileInfo.size);
    // You can use fileInfo.content, which is a Uint8Array, here

Copying strings to the clipboard using pure Javascript

You want to copy a string to the system clipboard in the browser without using any dependency like clipboard.js .


Use this function:

function copyStringToClipboard (str) {
   // Create new element
   var el = document.createElement('textarea');
   // Set value (string to be copied)
   el.value = str;
   // Set non-editable to avoid focus and move outside of view
   el.setAttribute('readonly', ''); = {position: 'absolute', left: '-9999px'};
   // Select text inside element;
   // Copy text to clipboard
   // Remove temporary element

Note: If the user selected anything when you ran the function, this selection will be cleared. If you need to preserve the selection, see this Hackernoon article for a more elaborate solution..

You can use it like this:

// Usage example:

It works by adding a temporary <textarea> element onto the DOM which is moved outside (credits to Angelos Charalis on Hackernoon for the original idea) the viewport in order to avoid wreaking havoc on screenreaders etc.

How to fix NodeJS request Error: Argument error, options.body


You’re using request to send a POST request with a body that should be JSON-encoded, but you are encountering an error similar to this:

Error: Argument error, options.body.
    at setContentLength (/home/uli/myproj/node_modules/request/request.js:434:28)
    at Request.init (/home/uli/myproj/node_modules/request/request.js:439:5)
    at new Request (/home/uli/myproj/node_modules/request/request.js:128:8)
    at request (/home/uli/myproj/node_modules/request/index.js:53:10)
    at (/home/uli/myproj/node_modules/request/index.js:61:12)

and, additionally this stacktrace:

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string or Buffer
    at write_ (_http_outgoing.js:647:11)
    at ClientRequest.write (_http_outgoing.js:622:10)
    at Request.write (/home/uli/myproj/node_modules/request/request.js:1501:27)
    at end (/home/uli/myproj/node_modules/request/request.js:546:18)
    at Immediate.<anonymous> (/home/uli/myproj/node_modules/request/request.js:575:7)
    at runCallback (timers.js:763:18)
    at tryOnImmediate (timers.js:734:5)
    at processImmediate (timers.js:716:5)


The error basically tells you that request can’t determine the length of the body, as you didn’t tell it how to encode the body and it isn’t a simple string or buffer. The solution is to tell request to use JSON body encoding by adding json: true to the options parameter (first argument to A valid options parameter looks like this:

const opts = {
    url: 'http://localhost:1234/api/myapi',
    body: {/* your body object */},
    json: true // <-- Add this line

How to fix KaTeX parse error: KaTeX doesn’t work in quirks mode


You’re using KaTeX on a website, but every time you try to render, you encounter the following error message:

Uncaught Error: KaTeX parse error: KaTeX doesn't work in quirks mode.
    at new e (VM697 katex.min.js:1)
    at Object.l [as render] (VM697 katex.min.js:1)


KaTeX requires a valid DOCTYPE declaration on your HTML page, so add this line at the top of your HTML file(s), above <html>

<!DOCTYPE html>

Thanks to @xymostech on GitHub for the original solution in the the KaTeX issue tracker:

How to fix Angular ‘TypeError: templateRef.createEmbeddedView is not a function’


You encounter an error message like this:

ERROR TypeError: templateRef.createEmbeddedView is not a function
    at ViewContainerRef_.createEmbeddedView (core.js:11389)
    at NgIf._updateView (common.js:2843)
    at NgIf.set [as ngIfElse] (common.js:2815)
    at updateProp (core.js:12602)
    at checkAndUpdateDirectiveInline (core.js:12313)
    at checkAndUpdateNodeInline (core.js:13876)
    at checkAndUpdateNode (core.js:13819)
    at debugCheckAndUpdateNode (core.js:14712)
    at debugCheckDirectivesFn (core.js:14653)
    at Object.eval [as updateDirectives] (MyComponent.html:1)

in a component where you have a source code similar to this

<div *ngIf="myCondition ; else elseSection">
    <!-- ... -->
<div #elseSection>
    <!-- ... -->


Whatever element you reference in the *ngIf else clause can’t be any arbitrary component, but it must be a ng-template.

In order to solve this, change <div #elseSection> to <ng-template #elseSection>. Note that using just <template> is deprecated since Angular4.

The resulting source code should look like this:

<div *ngIf="myCondition ; else elseSection">
    <!-- ... -->
<ng-template #elseSection>
    <!-- ... -->

How to fix Angular ‘Cannot find control with unspecified name attribute’


In your Angular2/4/5 application you see this error message:

Cannot find control with unspecified name attribute


Look for a statement in the HTML angular template like this:


The error message means that myCtrl can’t be found. Check if this variable is present in your class – it needs be a FormControl which you can import from @angular/forms:

import { FormControl } from '@angular/forms';

In my case, changing it to


fixed the issue

How to fix Angular4/5/6 ‘No provider for ControlContainer’


In your Angular2/4/5 application you’re getting the following error message:

No provider for ControlContainer ("<div class="recall-container mat-elevation-z8">


You have not added the @angular/forms FormsModule to your module’s import list.

Go to your app.module.ts and add this line to the imports:

import { FormsModule } from '@angular/forms';

and look for a line like this in your module definition:

imports: [ /* several import modules may be listed here */ ],

and add FormsModule like this (if there are already imports, add FormsModule to the list):

imports: [ FormsModule ],

How to use query string parameters in NodeJS request


You’re using the request library in order to make a HTTP GET request:

const request = require("request")

request.get("http://localhost:8000", function(err, response, body) {
    console.log(err, body);

Now you’re trying to add query parameters to the request. For this example, we’ll assume that you want to add one parameter: foo=bar


You can use the qs parameter like this:

const request = require("request")

request.get({url: "http://localhost:8000", qs: {"foo": "bar"}}, function(err, response, body) {
    console.log(err, body);

Note that just adding a qs parameter to request.get won’t work, you need to have a dictionary as first argument that contains at least {"url": <your URL>, "qs": {<one or multiple query parameters>}}

Credits to Daniel at StackOverflow

Disabling SSL certificate checking in unirest (NodeJS)


You want to make a HTTP request with unirest like this:

const unirest = require('unirest');

but you encounter the following error:

{ error: 
   { Error: unable to verify the first certificate
       at TLSSocket.<anonymous> (_tls_wrap.js:1088:38)
       at emitNone (events.js:86:13)
       at TLSSocket.emit (events.js:188:7)
       at TLSSocket._finishInit (_tls_wrap.js:610:8)
       at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:440:38) code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' } }


You can work around this problem by using strictSSL(false) like this:

const unirest = require('unirest');


Note however that this might have negative effects on the security of your application as this request will be vulnerable to man-in-the-middle attacks.