Special Characters being encoded in filename?

In my extension, users can save files, by providing an output filename, after modifying the original file (images).

One of my users wants to use special characters e.g. + or accented characters.

Android/Java/Appinventor (?) is encoding these special characters when creating the file.

For example, the user sends 3+500-1234.jpg as a file name,
the file is saved, but returned as 3%2B500-1234.jpg

There is obviously a character set requirement somewhere, but where? When the extension code receives the proposed filename or later when the file is created with File (java.io) ? And what needs to be done ?

Thanks :slight_smile:

Pertinent lines in the code:

try (final FileOutputStream stream = new FileOutputStream(eoutput)) {
        BitmapFactory.decodeFile(etarget,options).compress(format, quality, (OutputStream) stream);

        File file = new File(eoutput);

eoutput being a variable holding the absolute fileapath, including the filename and extension.

It all works with no issue other than the above.

This is most likely happening due to the URL conversion. There are a few places that can happen, both in the web interface and in the Android code. How is the user providing the file for selection? Is it done in the blocks or somewhere else?

No web interface that I am aware of, blocks like so:

Does the File.MakeFullPath return 3%2B500-1234.jpg? After saving, in the file explorer do you see it as 3%2B500-1234.jpg? And how are you querying back the saved file path?

1 Like

AH, yes it does

image

Sort of fixed it:

could be the best we can hope for ?

Inside your component, if you have a string that starts "file:" you should be able to do:

FileOutputStream o = null;
try {
  o = new FileOutputStream(new File(new URL(output).toURI()));
  ...
} catch (IOException e) {
  ...
} finally {
  if (o != null) {
    o.close();
  }
}
1 Like

Well hmm, I believe it should not be that way. + does not appear to be a restricted character:

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/FileUtils.java#1100

Except it's going through a URL conversion, and + is restricted in URLs since it has different semantics within a path component vs in a query string.

Thanks Evan, will test that out, looks like a keeper. Will report back once re-built.

@Kumaraswamy , however, gets my "Clever Sausage of the Day" award :wink:

It didn't cross my mind that the File component MakeFullPath was encoding it.

Hmm. I went back and reviewed RFC 1738, and it seems as though + isn't actually considered a restricted char at that particular point.

I wonder if this is the Java URL class being overly cautious.

FileUtil.java#L822 Seems to always pass the File through Uri, is this by choice? Are there specific cases where it'd make sense to directly return the path?

It's mostly for consistency since content: URIs are passed through, so we normalize everything to a URI. In other places, HTTP URIs are also supported (e.g., you can load a button background image from an HTTP URI)

1 Like

@ewpatton

Would this work instead, to simply convert the original filepath ?

eoutput = new URL(eoutput).toURI().toString();

I believe that URI's toString method will include the scheme at the beginning, so I don't think it will quite accomplish what you want.

This appears to work in testing:

image

(second line)
image

Great, although in your previous post you used toString() rather than getPath(), so I stand by my original analysis. :smiley:

1 Like

Just tested and working in extension. :clap: and thank you so much for your help and input, both @Kumaraswamy and @ewpatton :smiley:

3 Likes