Chrome on Windows adding trailing underscores to downloaded files?
Asked Answered
Y

10

14

I've got a rather odd situation happening, that I'm having difficulty tracking down in an existing Django application. One of the views, which inherits from APIView, returns with a file when a user makes a POST call. The endpoint works fine, but there's something odd happening when the downloaded file reaches the client machine. By the time the browser receives the file, the file extension has been renamed with a trailing underscore. (So suppose the file was originally "test.txt", the version that the client receives would be "test.txt_").

As near as I can figure, just before the response object is returned in the APIView, the content-type and content-disposition headers look correct. E.g.:

Content-Type: application/octet-stream
Content-Disposition: attachment;filename="test.txt"

That same file, when it shows up in Chrome downloads, is named "test.txt_" - with the trailing underscore. I've tried the same thing out in Firefox, and it seems to download correctly. Unfortunately, telling the majority of our users to switch browsers isn't going to fly.

I have tried:

  • Forcing a different content type (e.g.: instead of "application/octet-stream", try "application/text", just to see what happens). This had no effect.
  • Formatting the content disposition slightly different (e.g.: space between the semicolon and filename). This also had no effect.
  • Removed the double quotes around the filename in the content-disposition header. No effect.
  • Dropping breakpoints within the Rest Framework itself, but Visual Studio Code doesn't seem to trigger on these. (I'm not super-familiar with debugging through Visual Studio Code, so this may be my fault).
  • Stripped out any custom middleware, so the only remaining middleware are as follows:
corsheaders.middleware.CorsMiddleware
django.contrib.sessions.middleware.SessionMiddleware
django.middleware.locale.LocaleMiddleware
django.middleware.common.CommonMiddleware
django.middleware.csrf.CsrfViewMiddleware
django.contrib.auth.middleware.AuthenticationMiddleware
django.contrib.messages.middleware.MessageMiddleware

So far, any similar issues that other people have experienced seem to be slightly different (i.e.: Internet Explorer removing the period in the extension and replacing it with an underscore).

Any guesses on what might be happening here? I'm a bit stumped.

Yarndyed answered 25/3, 2019 at 15:30 Comment(0)
Y
6

I finally figured out what was going on here. The UI that was used to trigger the download was doing so through creating a temporary anchor tag (see the second answer here: Download data url file ). When it was doing so, it had two different cases. In one case, if downloading multiple files, it would change the file extension to .zip. In another case, if downloading a single file, it was still trying to append an extension, but the way the UI code was written, it was setting the extension to be an empty string. So the end result is a period being added, but no extension after that. For example, if the file being downloaded was "test.txt", it would end up as "test.txt.", which was then converted by Chrome to "test.txt_", on Windows, to make it a valid file extension.

Yarndyed answered 23/4, 2019 at 19:2 Comment(7)
Do you know how to remove it?Battologize
In our case, it ended up being a change in the UI code to quit putting on a trailing period.Yarndyed
Too bad, that's not enough. I am looking for a way to remove the preceding and trailing underscore.Battologize
If you make the same request via CURL or Postman, do you get the same results?Yarndyed
In fact, I am writting a service with python bottle and could let users download some files after a request. I would like to use its builtin function, static_file, and got the situation both of us met. I didn't try CURL or Postman because those are not in my toolkits. I am still looking for a way to work around it. But so far, it's a long shot.Battologize
I found that the user driven file name had spaces in it, told them not to do that and the problem went away.Heterolecithal
Thanks for this, I was testing my API via Swagger and swagger did the same thing as you mentioned.Cantlon
P
13

You have to remove "" from your file name

Change attachment; filename="filename.txt" to attachment; filename=filename.txt

Although seems like you won't be able to have spacing in file name

Pyelonephritis answered 1/4, 2022 at 15:1 Comment(1)
This was the answer for me. I solved it with this ugly javascript (ES6 required): const filename = response.headers.get('Content-Disposition')?.split(';')?.[1]?.split('=')?.[1]?.slice(1, -1);Edeline
Y
6

I finally figured out what was going on here. The UI that was used to trigger the download was doing so through creating a temporary anchor tag (see the second answer here: Download data url file ). When it was doing so, it had two different cases. In one case, if downloading multiple files, it would change the file extension to .zip. In another case, if downloading a single file, it was still trying to append an extension, but the way the UI code was written, it was setting the extension to be an empty string. So the end result is a period being added, but no extension after that. For example, if the file being downloaded was "test.txt", it would end up as "test.txt.", which was then converted by Chrome to "test.txt_", on Windows, to make it a valid file extension.

Yarndyed answered 23/4, 2019 at 19:2 Comment(7)
Do you know how to remove it?Battologize
In our case, it ended up being a change in the UI code to quit putting on a trailing period.Yarndyed
Too bad, that's not enough. I am looking for a way to remove the preceding and trailing underscore.Battologize
If you make the same request via CURL or Postman, do you get the same results?Yarndyed
In fact, I am writting a service with python bottle and could let users download some files after a request. I would like to use its builtin function, static_file, and got the situation both of us met. I didn't try CURL or Postman because those are not in my toolkits. I am still looking for a way to work around it. But so far, it's a long shot.Battologize
I found that the user driven file name had spaces in it, told them not to do that and the problem went away.Heterolecithal
Thanks for this, I was testing my API via Swagger and swagger did the same thing as you mentioned.Cantlon
E
2

Our environment has a document storage system that contains documents with the attributes DocumentName and ContentType. In some cases, the content type would return with spaces appended to the end of the string like "pdf ".

In Internet Explorer the output would truncate the end of the string while Chrome would convert the extra spaces to underscores giving me this filename: "file.pdf______________"

To resolve I simply truncate the string.

public string getFileName(string docName, string contentType) {
    string fileName = docName + "." + contentType.Trim();

    return fileName;
}
Emission answered 17/9, 2020 at 17:52 Comment(0)
C
2

I encountered the same problem. Let's say your download file name is "my_report.csv" Then before doing the download operations get rid of " characters

fileName  = fileName.replace('"','') // replacing one " charcter
fileName  = fileName.replace('"','') // replacing second " character

This will resolve your issue.

Confucianism answered 28/10, 2021 at 18:55 Comment(1)
Thanks, this is what worked for me! "It's a simple spell but quite unbreakable!"Ethical
C
0

My solution in ASP.NET core

[HttpGet("pdf/{fileId}")]
public IActionResult GetPdfFile([FromRoute]int fileId)
{
    var result = Repo.GetFile(fileId);
    Response.Headers.Add("Content-Disposition", $"inline; filename={result.FileName}");
    return File(result.Data, "application/pdf");
}
Cadent answered 5/9, 2020 at 8:9 Comment(0)
S
0

I resolved this issue with replace white space in file name by a character like -.

Sugarplum answered 9/11, 2020 at 10:59 Comment(0)
P
0

This was happening for me when the filename included a comma.

    lastname,MD.pdf

browser would download filestream as

    _lastname,MD.pdf_ 

Adding code to remove a potential comma from the filename resolved the issue and made it download as expected.

    filename = filename.Replace(",", ""); // replace comma characters with blank

now downloads as

    lastnameMD.pdf
Persian answered 6/6, 2022 at 21:54 Comment(0)
T
0

In my case there was a space as a first character, and it was replaced to underscore. So I simply removed the space :-)

Teen answered 26/7, 2022 at 7:52 Comment(0)
P
0

I have got the same problem. In my case i have solved it with changing link from http://127.0.0.1:5000/api?file=curl-8.5.0.tar.gz/ to http://127.0.0.1:5000/api?file=curl-8.5.0.tar.gz.
Notice I cast away forward slash at the end of the URL.

Polemics answered 29/1 at 13:49 Comment(0)
M
0

In my case it happened with Google Chrome in Linux.

When I got the Content-Disposition header of the AxiosResponse I got something like this:

"content-disposition": "attachment; filename=\"filename.txt\""

So, I checked this specific case and used 2 splits to get "filename.txt", similar to this snippet:

// This is how I got the attachment information in the AxiosResponse.
const headers = {
  "content-disposition": "attachment; filename=\"filename.txt\""
};

const expectedFileName = "filename.txt";

try {
  // Get the filename WITHOUT the "\".
  const fileName = headers["content-disposition"]
    .split('filename=')[1]
    .split("\"")[1];

  if (expectedFileName === fileName) {
    console.log(`OK. Final filename: ${fileName}`);
  } else {
    console.log('KO');
  }
}
catch(e) {
  console.error('Find another way.');
  console.error(e);
}
Moshemoshell answered 3/5 at 14:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.