How do I use QDesktopServices::openUrl with 'file:' URL containing '#'?

SteveTJS picture SteveTJS · Jul 22, 2015 · Viewed 7.8k times · Source

In my application, I generate a HTML file that I want to open by clicking on a button. So my file is named, for example:

QString file = "F:/the_path/to_the_/generated_html_file.html";

On Windows I change it to:

file = "file:///F:/the_path/to_the_/generated_html_file.html";

so that I can open it with :

QDesktopServices::openUrl(QUrl(file));

and it opens in the default browser.

But when the character # is present in the path or file name, it doesn't work any more and it seems that the URL is truncated just after the #.

For example, if I name the file generated#_html_file.html, I get this error message:

ShellExecute 'F:/the_path/to_the_/generated' failed (error 2).

Why does that happen, and how can I avoid it?

Answer

Toby Speight picture Toby Speight · Jul 22, 2015

In a URL, # is a character that delimits the 'fragment identifier' from the resource location. To reference a file: URL with a literal #, it needs to be escaped (as %23).

Reference: RFC 1738:

The character "#" is unsafe and should always be encoded because it is used in World Wide Web and in other systems to delimit a URL from a fragment/anchor identifier that might follow it.

As noted by SteveTJS, the static method QUrl::fromLocalFile() is provided for this purpose, so you can write

QDesktopServices::openUrl(QUrl::fromLocalFile(file));

instead of

QDesktopServices::openUrl(QUrl(file));

This will

  1. Prepend the file: protocol identifier and // empty hostname
  2. Convert native path separator to / (if different)
  3. Encode any non-safe characters for URL.