Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

send_file doesn't urlencode ':/' in unicode attachment_filename #3074

Closed
i-akhmadullin opened this issue Jan 15, 2019 · 5 comments

Comments

@i-akhmadullin
Copy link

commented Jan 15, 2019

Expected Behavior

When sending files with unicode filename (with : or /) they should be downloaded with name from filename* field.

# -*- coding: utf-8 -*-
import os
from flask import Flask, send_from_directory
app = Flask(__name__)
@app.route('/test/', methods=['GET'])
def test_route():
    tmp_dir = os.getcwd()
    tmp_filename = __file__
    attachment_filename = u'тест:тест_тест.py'
    return send_from_directory(
        tmp_dir,
        tmp_filename,
        as_attachment=True,
        attachment_filename=attachment_filename
    )
if __name__ == '__main__':
    app.run(host='::', port=5000)

Actual Behavior

Some browsers (Chrome-based/Safari) ignore filename* field when it contains colon or slash. For example file тест:тест_тест.py gets downloaded in Chrome/Safari as __.py but in Firefox as тест_тест_тест.py which is acceptable in my opinion.

Flask response:
Content-Disposition: attachment; filename*="UTF-8''%D1%82%D0%B5%D1%81%D1%82:%D1%82%D0%B5%D1%81%D1%82_%D1%82%D0%B5%D1%81%D1%82.py"; filename=":_.py"

Environment

  • Python version: 2.7.15
  • Flask version: 1.0.2
  • Werkzeug version: 0.14.1
@eladm26

This comment has been minimized.

Copy link
Contributor

commented Feb 19, 2019

Hi @i-akhmadullin
according to the RFC: both "filename" and "filename*" are present in a single header field value, recipients SHOULD pick "filename*" and ignore "filename"
So it seems like an issue of chrome rather than flask.

@davidism

This comment has been minimized.

Copy link
Member

commented Feb 19, 2019

This was working in Chrome when I implemented this. If they're changing behavior, that's incorrect and needs to be reported to them. I don't think Flask can do anything about it because it still needs to send both for compatibility with other clients.

@i-akhmadullin

This comment has been minimized.

Copy link
Author

commented Feb 19, 2019

This issue is about encoding colon and slash in attachment filename, not about filename/filename*.
If we encode colon and slash characters then file gets downloaded with a utf8-name, but with underscores instead colons and slashes. But otherwise this is a lot better result than ascii-only filename (тест_тест_тест.py vs _.py).

Flask uses url_quote from werkzeug where :/ are listed as safe characters, so maybe it just an oversight that they are not escaped.

'filename*': "UTF-8''%s" % url_quote(attachment_filename),

https://github.com/pallets/werkzeug/blob/master/werkzeug/urls.py#L518

@davidism

This comment has been minimized.

Copy link
Member

commented Feb 19, 2019

Your description in "actual behavior" makes no mention of how ":/" relate to the issue, it just mentions "filename" and "filename*". Could you review and make sure the issue accurately represents what you're trying to describe?

@i-akhmadullin

This comment has been minimized.

Copy link
Author

commented Feb 19, 2019

@davidism sorry for the confusion, should be clearer now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.