DEV Community

Cover image for Handling files in enterprise web solutions

Handling files in enterprise web solutions

Correct file handling can be cumbersome without proper system integration and selection of which applications can handle what types of files.

Web solutions have previously been disconnected from this because of limitations in the browser to system integration.

This is no longer the case, and this post will cover the key parts of making a solution that works.

To make things more concrete, we will look at how to create a simple GeoJSON viewer application that will automatically open and display GeoJSON files when double-clicking them (or selecting the app on "Open with...").

Note: This feature is desktop only

File Handling in manifest.json

In the file manager and the desktop view of most operating systems, there is a file handling UI that directs the user to use a certain app to handle the chosen file. Previously, this was limited to native app installations, but now, it's possible for web applications to register handlers tied to PWAs that will handle files matching certain extension patterns.

Thomas Steiner has created a great article about this here:

https://developer.chrome.com/docs/capabilities/web-apis/file-handling

What's needed

  1. file_handlers entries in manifest.json
  2. Code to handle loading the files
  3. Installation of the web application

Let's look at these one by one.

file_handlers in manifest.json

Note: In order to make the web application 'installable', a manifest file needs to be present with minimal information as described here.

Inside the manifest file, create a section with the key file_handlers. This contains an array of the file types that the application can handle (accept), which URL to open (action, must be within the scope of the installed PWA), icons and launch_type, describing if new instances should be made for each file on "Open with..." selection.

...
"file_handlers": [
  {
    "action": "./?log=y",
    "accept": {
      "application/geo+json": [".geojson"]
    },
    "icons": [
      {
        "src": "./images/treasure-map-256.png",
        "sizes": "256x256",
        "type": "image/png"
      }
    ],
    "launch_type": "multiple-clients"
  }
]
...
Enter fullscreen mode Exit fullscreen mode

In our case, we are interested in handling files with the .geojson extension and we will send it to our PWA with an additional query parameter to enable debug logging (log=y).

File loading handler(s)

When the PWA is opened by the OS via an "Open with..." action, the file(s) selected will be available through the launchQueue interface:

if ('launchQueue' in window && 'files' in LaunchParams.prototype) {
  launchQueue.setConsumer(async (launchParams) => {
    if (!launchParams.files.length) {
      return;
    }
    for (const fileHandle of launchParams.files) {
      // Handle the file.
      const file = await fileHandle.getFile();
      this.loadGeoJSONFile(file);
    }
  });
} else {
  console.log("File Handling API NOT supported");
}
Enter fullscreen mode Exit fullscreen mode

Installation and usage

Open the application in a supported browser and click the install icon in the address bar.

Install PWA

Then go to the file explorer, right click a GeoJSON file (with the .geojson extension) and see how the freshly installed PWA is now registered to handle GeoJSON files.

Open with PWA

On first launch, the user is prompted to check if this should be the default behavior:

Default open with

When the PWA starts, the GeoJSON is loaded, passed to the map and immediately displayed:

GeoJSON loaded

Note: The collapsible activity log in the bottom of the screen is activated because of the additional log=y passed to the application.

Windows and Edge

The section above describes how the flow looks when using Chrome and Ubuntu. Here we will go through the same flow, but using Edge on Windows.

Credit: @kennethrohde

Installation:
Edge Install PWA

Open .geojson file with the PWA:
Edge Open With

Loading GeoJSON:
Edge Loading GeoJSON

OpenLayers

In order to display the GeoJSON features on a map, we will use OpenLayers, which is a very powerful open-source mapping library that is also very simple to use.

In this post, we will not dive into all the details, so I will just show the snippets related to initializing the map and adding the GeoJSON data on top:

...
// Init map
this.#map = new ol.Map({
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM(),
    }),
    this.#vectorLayer,
  ],
  target: this.#mapEl,
  view: new ol.View({
    center: [0, 0],
    zoom: 2,
  }),
});

...

// Load GeoJSON
plotGeoJSON(obj) {
  const features = new ol.format.GeoJSON({
    featureProjection: 'EPSG:3857'
  }).readFeatures(obj);

  const vectorSource = new ol.source.Vector({ features });

  this.#vectorLayer.setSource(vectorSource);

  setTimeout(() => {
    this.#map.getView().fit(vectorSource.getExtent(), { duration: 1000 });
  }, 500);
}
Enter fullscreen mode Exit fullscreen mode

Creating GeoJSON files

Inside the project repository, there are a few GeoJSON samples generated with the awesome GeoJSON editor here: geojson.io. This web application let's you create features by drawing on a map and the features are then immediately reflected in a GeoJSON format on the right side of the screen.

Screenshot of geojson.io

TIL GitHub has a nice GeoJSON viewer built-in:

GitHub GeoJSON

Conclusion

Having the option of adding file handling on a system level is a very powerful feature and also extremely useful, e.g for enterprise tools to optimize workflows.

The effort involved in adding the feature in a PWA is close to nothing and personally I enjoyed experimenting with this very much.

The code is available here: https://github.com/larsgk/filehandling-geojson

The application is hosted here: https://larsgk.github.io/filehandling-geojson

Enjoy ;)

Top comments (4)

Collapse
 
prushforth profile image
Peter Rushforth

Nice ideas to try out, Lars!

Maybe also easy to integrate GeoJSON with maps in our speculative polyfill for maps in HTML, via our custom elements. Cheers!

Collapse
 
denladeside profile image
Lars Knudsen 🇩🇰

Hi Peter,

Thanks for bringing my attention to the work you've doing on maps in HTML. Looks very interesting!

Would you like to try to replicate my example using a pure HTML version using it? Could be educational for others considering different approaches to web components (and file handling, of course;)).

Collapse
 
prushforth profile image
Peter Rushforth

Hi Lars!

I took up your challenge and made a MapML version of the viewer, which uses our GeoJSON API to load GeoJSON file resources as layers in the viewer.

It did not happen as smoothly as I would have liked, because our current assumption was that the element is in light DOM! What a surprise for me when that assumption proved incorrect. However I did log the issue and it seems quite fixable. Anyway, I created a modified version of our viewer in a fork of your nice demo and I put it here. Feel free to comment in the issues if you like. It "mostly works", with console logging being due to the light/shadow issue.

Thread Thread
 
denladeside profile image
Lars Knudsen 🇩🇰

That looks awesome 😎 maybe you want to make a follow-up post to mine with the comparison?