Warning Users About The Windows Explorer Zip Archive Preview In JavaScript
In recent years, on a Windows computer, if you double-click on a .zip
file - the same way you would navigate into any Folder in the file system - Windows doesn't automatically extract the .zip
file contents. Instead, it opens an "Explorer Preview" of the archive, allowing you to view the contents of the archive without actually extracting the embedded files. While this provides some conveniences for the user, it can also break the user experience (UX) in non-intuitive ways. As such, it can sometimes be helpful to alert the user about this non-obvious Explorer experience using JavaScript.
At InVision, I produce a lot of .zip
archive files. Which is why I spend so much time writing about the DEFALTE
and STORE
compression methods, incrementally generating and streaming Zip files on-the-fly, and executing the zip
command from a given working directory (using either a proxy shell command or the new directory
attribute in Lucee's CFZip
tag).
Many of the Zip archive files that I generate are actually "rich reports" that contain an interactive .html
file. This HTML file almost always references other files embedded within the archive; which works gang busters, unless you're using the aforementioned Windows Explorer "preview archive" experience. You can tell that you're using this experience if Windows Explorer includes the .zip
file extension in the "folder path" and shows you Extraction tools within the toolbar:
As you can see, the .zip
file extension is in the Windows Explorer folder path. We haven't unarchived / extracted the file - we've entered into the "archive preview". The problem here is that if you then double-click on the index.html
file, Windows extracts that file on-the-fly into a temporary folder:
As you can see, while the index.html
file opened in the Microsoft Edge browser as one would hope, it's opening from an AppData/Local/Temp/
location - not from the "Downloads" folder in which the Zip archive is actually stored. In many cases, this isn't a problem. However, if the index.html
file references other files within the .zip
archive, the relative file paths that you have to use in such a case will not work from this AppData/Local/Temp/
location.
So, any linked images, style sheets, and JavaScript files will break (fail to load in the index.html
file).
What you end up with is a broken user experience despite the fact that the user double-clicked into the .zip
file in the same way that they would have double-clicked into any other type of Folder. Windows has entered an "Uncanny Valley" - it has something that mostly looks and acts like a "Folder", but which leaves much to be desired.
In order to help the user understand why their experience is breaking, we can use JavaScript to put a spotlight on the contextual problem. Thankfully, when Windows Explorer enters this "preview" mode, the .zip
file-extension is present in the window.location.href
value. Which means, we can look for this value on page-load and then alert()
the user that they've entered into a not-quite-a-folder experience:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>
My Archive!
</title>
<script type="text/javascript">
(function() {
// In Windows Explorer, double-clicking on a ZIP file doesn't extract
// the .zip file, it just "explores" it. If a file within the ZIP is
// then opened, any embedded paths are broken. Let's alert the user
// to this fact if the URL looks liks it contains a ".zip" in it.
if ( window.location.href.search( new RegExp( "\.zip[\\/]", "i" ) ) >= 0 ) {
alert(
"It looks like you are viewing this report from a zipped export file (.zip). " +
"If some report assets are not displayed correctly, please fully extract " +
"the zip file and then reopen the html file."
);
}
})();
</script>
<!-- .... truncated for demo .... -->
</head>
<body>
<!-- .... truncated for demo .... -->
</body>
</html>
Here, we're using the Regular Expression pattern:
\.zip[\\/]
... to see if the .zip
string is located right before a path-separator (either back-slash or forward-slash). And, if that pattern is found, we open up a native alert()
outlining the potential issue.
Now, if the user double-clicks into the .zip
file, enters the Windows Explorer archive preview mode, and then double-clicks into the index.html
file, they will see the following:
This is not a great user experience (UX); but, it's a whole heck of a lot better than just letting the file open and allowing the embedded resources to break without any explanation. At least with the JavaScript alert, we can hopefully guide the user to a working solution.
Epilogue on Using Data URLs to Embed Resources Within a Single File
One possible work-around for this Windows Explorer archive preview mode problem is to not have any external resources. And, one way to accomplish that is to embed any external resources as Data URLs directly within the index.html
file. So, instead of linking to a relative ./files/report.png
image file, you can embed the binary image data as a Base64-encoded value right within the <img>
tag itself:
<img src="data:image/png;base64,R0lGODlhEAA{ ... really long value ... }" />
To be clear, this works. But, it should only be used when you have a relatively small amount of data to embed. In my experience, including a lot of data as Base64-encoded values quickly leads to massive file sizes and slow load times (depending on where you're loading the file from). It also means that the user cannot easily "explore" the linked files - something that may be a critical part of the user experience. As such, your mileage may vary.
Want to use code from this post? Check out the license.
Reader Comments
So, the
\.zip[\\/]
pattern is not working in all contexts. Some temporary URLs appear to use.zip.
in the URL. As such, I've taken to softening the pattern matching to be\.zip\b
. This will cover a wider range of URLs and is still unlikely to generate a false-positive match.