Вероятно, вы хотите передать "a"
в качестве аргумента режима.
with open("foo", "a") as f:
f.write("cool beans...")
Существуют другие перестановки аргумента режима для обновления (+), усечения (w) и двоичного (b) режима, но начиная с только "a"
, это ваш лучший выбор.
Обсуждается это, включая ссылки на проверку браузера и обратную совместимость, в предлагаемом RFC 5987 , «Набор символов и кодирование языка для параметров протокола заголовка гипертекстового протокола (HTTP)».
RFC 2183 указывает, что такие заголовки должны кодироваться в соответствии с RFC 2184 , который был устареван RFC 2231 , охватываемый проект RFC выше.
У нас была аналогичная проблема в веб-приложении, и в итоге я прочитал имя файла из HTML <input type="file">
и установил это в кодировке url в новом HTML <input type="hidden">
. Конечно, нам пришлось удалить путь, подобный «C: \ fakepath», который возвращается некоторыми браузерами.
Конечно, это напрямую не отвечает на вопрос OP, но может быть решением для других.
Я нашел решение, которое работает для всех моих браузеров (т. е. всех браузеров, которые я установил - IE8, FF16, Opera 12, Chrome 22).
Мое решение описано в другом потоке: g0] Java servlet download filename специальные символы
Мое решение основано на том, как браузеры пытаются считывать значение из параметра filename
. Если в параметре filename
(например, filename*=utf-8''test.xml
) нет кодировки, браузеры ожидают, что это значение закодировано в собственной кодировке браузера.
Различные браузеры ожидают различной собственной кодировки. Обычно исходная кодировка браузера - utf-8 (FireFox, Opera, Chrome). Но исходная кодировка IE - Win-1250. [Я не знаю ничего о других браузерах.)
Следовательно, если мы поместим значение в параметр filename
parametr, который закодирован utf-8 / win-1250 в соответствии с браузером пользователя, он должен работать , По крайней мере, это работает для меня.
Короче говоря, если у нас есть файл с именем omáčka.xml
, для FireFox, Opera и Chrome я отвечу на этот заголовок (закодированный в utf-8):
Content-Disposition: attachment; filename="omáčka.xml"
, а для IE I отвечает этот заголовок (закодирован в win-1250):
Content-Disposition: attachment; filename="omáèka.jpg"
Пример Java - это в моем сообщении , о котором упоминалось выше.
Я обычно кодирую URL-адрес (с% xx) именами файлов и, похоже, работает во всех браузерах. Возможно, вы захотите сделать некоторые тесты.
Поместите имя файла в двойные кавычки. Решил проблему для меня. Например:
Content-Disposition: attachment; filename="My Report.doc"
http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download
&
, %
, #
и т. Д. Поэтому он решает это.
– mmcrae
26 August 2016 в 17:17
Если вы используете бэкэнд nodejs, вы можете использовать следующий код, который я нашел здесь здесь
var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''"
+ encodeRFC5987ValueChars(fileName);
function encodeRFC5987ValueChars (str) {
return encodeURIComponent(str).
// Note that although RFC3986 reserves "!", RFC5987 does not,
// so we do not need to escape it
replace(/['()]/g, escape). // i.e., %27 %28 %29
replace(/\*/g, '%2A').
// The following are not required for percent-encoding per RFC5987,
// so we can allow for a little better readability over the wire: |`^
replace(/%(?:7C|60|5E)/g, unescape);
}
encodeURI(str)
. В качестве примера с датами в имени файла: encodeURIComponent('"Kornél Kovács 1/1/2016')
= & gt; «Kornél Kovács 1% 2F1% 2F2016» vs. encodeURI('"Kornél Kovács 1/1/2016')
= & gt; «Kornél Kovács 1/1/2016»
– gdibble
17 May 2016 в 18:13
В PHP это сделало это для меня (если имя файла закодировано в UTF8):
header('Content-Disposition: attachment;'
. 'filename="' . addslashes(utf8_decode($filename)) . '";'
. 'filename*=utf-8\'\'' . rawurlencode($filename));
Протестировано против IE8-11, Firefox и Chrome. Если браузер может интерпретировать filename * = utf-8 , он будет использовать версию имени файла UTF8, иначе он будет использовать декодированное имя файла. Если ваше имя файла содержит символы, которые не могут быть представлены в ISO-8859-1, вы можете использовать вместо этого iconv
.
Я использую следующие фрагменты кода для кодирования (предполагается, что имя_файла содержит имя файла и расширение файла, то есть: test.txt):
PHP:
if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $fileName ) . '"' );
}
else
{
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $fileName ) );
}
Java:
fileName = request.getHeader ( "user-agent" ).contains ( "MSIE" ) ? URLEncoder.encode ( fileName, "utf-8") : MimeUtility.encodeWord ( fileName );
response.setHeader ( "Content-disposition", "attachment; filename=\"" + fileName + "\"");
rawurlencode
в PHP, по крайней мере, для заголовка filename*=
, поскольку value-chars
используется в ext-value
RFC 6266- & gt; RFC 5987 (см. tools.ietf.org/html/rfc6266 # section-4.1 & amp; tools.ietf.org/html/rfc5987#section-3.2.1 ) не позволяет пространство без процента ускорения (filename=
, с другой стороны , кажется, что он может позволить пространство, не ускользая, хотя здесь должен присутствовать только ASCII). Нет необходимости кодировать с полной строгостью rawurlencode, поэтому несколько символов могут быть неизображены: gist.github.com/brettz9/8752120
– Brett Zamir
1 February 2014 в 15:06
Content-Disposition
и создавать очень интересные имена файлов (они будут сгенерированы с вашего пути). Таким образом, единственным решением для поддержания здравого смысла является установка Content-Disposition: attachment
и передача имени файла в качестве последнего компонента пути:
– Julik
29 May 2016 в 20:09
Я знаю, что это старый пост, но он по-прежнему очень важен. Я обнаружил, что современные браузеры поддерживают rfc5987, что позволяет кодировать utf-8, процент кодируется (кодируется по URL). Тогда Naïve file.txt становится:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari (5) не поддерживает это. Вместо этого вы должны использовать стандарт Safari для записи имени файла непосредственно в кодированном заголовке utf-8:
Content-Disposition: attachment; filename=Naïve file.txt
IE8 и более старые не поддерживают его, и вам нужно использовать стандарт IE для utf -8, процентное кодирование:
Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt
В ASP.Net я использую следующий код:
string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.Browser.Browser == "Safari")
contentDisposition = "attachment; filename=" + fileName;
else
contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);
Я протестировал выше, используя IE7, IE8, IE9, Chrome 13 , Opera 11, FF5, Safari 5.
Обновление ноября 2013:
Вот код, который я использую в настоящее время. Я все еще должен поддерживать IE8, поэтому я не могу избавиться от первой части. Оказывается, браузеры на Android используют встроенный менеджер загрузки Android, и он не может достоверно анализировать имена файлов стандартным способом.
string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.UserAgent != null && Request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android)
contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(fileName) + "\"";
else
contentDisposition = "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);
Вышеописанное теперь протестировано в IE7-11, Chrome 32, Opera 12 , FF25, Safari 6, используя это имя для загрузки: 你好 abcABCæøåÆØÅääüïëêîâéíóóúúññ½§! # ¤% & amp; () = `@ £ $ € {[]} +'¨ ^ ~ '-_,;. Txt
В IE7 он работает для некоторых персонажей, но не для всех. Но кто сейчас интересуется IE7?
Это функция, которую я использую для создания безопасных имен файлов для Android. Обратите внимание, что я не знаю, какие символы поддерживаются на Android, но что я проверял, что они работают наверняка:
private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~'=()[]{}0123456789".ToDictionary(c => c);
private string MakeAndroidSafeFileName(string fileName)
{
char[] newFileName = fileName.ToCharArray();
for (int i = 0; i < newFileName.Length; i++)
{
if (!AndroidAllowedChars.ContainsKey(newFileName[i]))
newFileName[i] = '_';
}
return new string(newFileName);
}
@TomZ: я тестировал в IE7 и IE8, и оказалось, что я сделал не нужно избегать апострофа (').
@Dave Van den Eynde: объединение двух имен файлов в одной строке, как в соответствии с RFC6266, за исключением Android и IE7 + 8, и я обновил код для отражения это. Спасибо за предложение.
@Thilo: Не знаю о GoodReader или любом другом не-браузере. Возможно, вам повезло с использованием подхода Android.
@Alex Жуковский: Я не знаю, почему, но, как обсуждалось в Connect , это не работает ужасно хорошо.
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt
и пропустить браузерный обнюхивание? Будет ли это работать?
– Dave Van den Eynde
8 November 2013 в 16:02
В ASP.NET Web API я кодирую имя файла:
public static class HttpRequestMessageExtensions
{
public static HttpResponseMessage CreateFileResponse(this HttpRequestMessage request, byte[] data, string filename, string mediaType)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new MemoryStream(data);
stream.Position = 0;
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType =
new MediaTypeHeaderValue(mediaType);
// URL-Encode filename
// Fixes behavior in IE, that filenames with non US-ASCII characters
// stay correct (not "_utf-8_.......=_=").
var encodedFilename = HttpUtility.UrlEncode(filename, Encoding.UTF8);
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment") { FileName = encodedFilename };
return response;
}
}
[/g0] [/g1]
RFC 6266 описывает « Использование поля заголовка Content-Disposition в протоколе передачи гипертекста (HTTP) ». Цитата из этого:
6. Вопросы интернационализации
Параметр «
filename*
» (, раздел 4.3 ), используя кодировку, определенную в [ RFC5987 ], позволяет сервер для передачи символов вне набора символов ISO-8859-1, а также необязательно указать используемый язык.И в разделе примеров :
Этот пример аналогичен приведенному выше, но добавляет параметр «filename» для совместимости с пользовательскими агентами, не реализующими RFC 5987 :
Content-Disposition: attachment; filename="EURO rates"; filename*=utf-8''%e2%82%ac%20rates
Примечание. Те пользовательские агенты, которые не поддерживают кодировку RFC 5987 , игнорируют «
filename*
», когда это происходит после «filename
».In Приложение D также имеется длинный список предложений по повышению интероперабельности. Он также указывает на сайт, который сравнивает реализации . Текущие тесты с полным прохождением, подходящие для общих имен файлов, включают в себя:
- attwithisofnplain : простое имя файла ISO-8859-1 с двойными кавычками и без кодирования. Для этого требуется имя файла, которое является ISO-8859-1 и не содержит знаков процента, по крайней мере, не перед шестнадцатеричными цифрами.
- attfnboth : два параметра в порядке описано выше. Должен работать для большинства имен файлов в большинстве браузеров, хотя IE8 будет использовать параметр «
filename
».Что RFC 5987 в свою очередь ссылается на RFC 2231 , который описывает фактический формат. 2231 в первую очередь предназначен для почты, а 5987 сообщает нам, какие части могут использоваться для заголовков HTTP. Не путайте это с заголовками MIME, используемыми внутри тела
multipart/form-data
HTTP , который определен, в частности, RFC 2388 ( раздел 4.4 )) и проект HTML 5 .
В моем сценарии «download.php» (на основе этот блогпост и ] был указан следующий код: Это использует стандартный способ filename = "...", если используются только iso-latin1 и «безопасные» символы; если нет, он добавляет имя файла * = UTF-8 '', закодированное по URL-адресу. Согласно $il1_filename = utf8_decode($filename);
$to_underscore = "\"\\#*;:|<>/?";
$safe_filename = strtr($il1_filename, $to_underscore, str_repeat("_", strlen($to_underscore)));
header("Content-Disposition: attachment; filename=\"$safe_filename\""
.( $safe_filename === $filename ? "" : "; filename*=UTF-8''".rawurlencode($filename) ));
Окончательная заметка: макс. размер для каждого поля заголовка составляет 8190 байт на apache. UTF-8 может содержать до четырех байтов на символ; после rawurlencode это x3 = 12 байт на один символ. Довольно неэффективно, но теоретически теоретически возможно иметь более 600 «улыбок»% F0% 9F% 98% 81 в имени файла.
Я тестировал следующий код во всех основных браузерах, включая более старых Исследователей (через режим совместимости), и он хорошо работает везде:
$filename = $_GET['file']; //this string from $_GET is already decoded
if (strstr($_SERVER['HTTP_USER_AGENT'],"MSIE"))
$filename = rawurlencode($filename);
header('Content-Disposition: attachment; filename="'.$filename.'"');
в asp.net mvc2 я использую что-то вроде этого:
return File(
tempFile
, "application/octet-stream"
, HttpUtility.UrlPathEncode(fileName)
);
Я предполагаю, что если вы не используете mvc (2), вы можете просто закодировать имя файла, используя
HttpUtility.UrlPathEncode(fileName)
Content-Disposition: filename="foo, bar.pdf"
. Результатом является то, что firefox загружает файл правильно, но поддерживает расширение.part
(например,foo,bar.pdf-1.part
). Тогда, конечно, файл не откроется правильно, потому что приложение не связано с.part
. Другие символы ASCII, похоже, работают нормально. – catchdave 11 January 2012 в 02:09