سؤال

أنا أستخدم كائن HTTPContext الذي تم تنفيذه في Httphandler Child لتنزيل ملف ، عندما يكون لدي أحرف غير ASCII باسم الملف ، يبدو غريبًا في IE بينما يبدو جيدًا في Firefox.

أدناه هو الرمز:-

       context.Response.ContentType = ".cs";
context.Response.AppendHeader("Content-Length", data.Length.ToString());
context.Response.AppendHeader("Content-Disposition", String.Format("attachment; filename={0}",filename));
        context.Response.OutputStream.Write(data, 0, data.Length);

context.Response.Flush();

عندما أقوم بتزويد 'ã' '' '' '' '' '' '' 'ã' '' '' '' '' '' '' '' ã ã في حقل اسم الملف ، يبدو مختلفًا عن ما لدي في الملف اسمه يبدو جيدًا في Firefox. لم تكن إضافة encodingtype و charset لا فائدة منها.

في IE هو "ãƒå¸"'ä''ö''ü''ó''ß''ä''ö'"ãƒÂ¼ '_' ãƒÂ³ 'وفي Firefox هو' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ã ã '.

أي فكرة كيف يمكن إصلاح هذا؟

هل كانت مفيدة؟

المحلول

كان لدي مشكلة مماثلة. عليك أن تستخدم httputily.urlencode أو server.urlencode لترميز اسم الملف. كما أتذكر أن Firefox لم يكن بحاجة إليه. علاوة على ذلك ، دمر اسم الملف عند ترميز عنوان URL. رمز بلدي:

// IE needs url encoding, FF doesn't support it, Google Chrome doesn't care
if (Request.Browser.IsBrowser ("IE"))
{
    fileName = Server.UrlEncode(fileName);
}

Response.Clear ();
Response.AddHeader ("content-disposition", String.Format ("attachment;filename=\"{0}\"", fileName));
Response.AddHeader ("Content-Length", data.Length.ToString (CultureInfo.InvariantCulture));
Response.ContentType = mimeType;
Response.BinaryWrite(data);

تعديل

لقد قرأت المواصفات بعناية أكبر. أولاً RFC2183 ينص علي:

يقيد النحو الحالي [RFC 2045] قيم المعلمة (وبالتالي أسماء ملفات تحديد المحتوى) إلى US-ASCII.

ولكن بعد ذلك وجدت إشارات مفادها أن [RFC 2045] مطلقة ويجب الإشارة إلى المرء RFC 2231, ، التي تنص على:

تتم إعادة استخدام العلامات النجمية ("*") لتوفير المؤشر على وجود معلومات مجموعة الأشرفة وترميزها. يتم استخدام عرض أسعار واحد ("" ") لحكم مجموعة الأحرف والمعلومات اللغوية في بداية قيمة المعلمة. يتم استخدام علامات النسبة المئوية ("٪") كعلم تشفير ، والذي يتفق مع RFC 2047.

مما يعني أنه يمكنك استخدام urlencode للرموز غير ASCII ، طالما قمت بتضمين الترميز كما هو مذكور في RFC. هنا مثال:

string.Format("attachment; filename=\"{0}\"; filename*=UTF-8''{0}", Server.UrlEncode(fileName, Encoding.UTF8));

لاحظ أن filename يتم تضمينه بالإضافة إلى filename* للتوافق للخلف. يمكنك أيضًا اختيار ترميز آخر وتعديل المعلمة وفقًا لذلك ، ولكن UTF-8 يغطي كل شيء.

نصائح أخرى

قد يكون httputily.urlpathencode خيارًا أفضل. لأن urlencode سوف يحل محل المساحات بعلامات '+'.

بالنسبة لي هذا الحل يعمل على جميع المتصفحات الرئيسية:

Response.AppendHeader("Content-Disposition", string.Format("attachment; filename*=UTF-8''{0}", HttpUtility.UrlPathEncode(fileName).Replace(",", "%2C"));
var mime = MimeMapping.GetMimeMapping(fileName);
return File(fileName, mime);

باستخدام ASP.NET MVC 3.

الاستبدال ضروري ، لأن Chrome لا يحب الفاصلة (،) في قيم المعلمات: http://www.gangarasa.com/lets-do-goodcode/tag/err_response_headers_multiple_content_disposition/

قد ترغب في القراءة RFC 6266 وانظر إلى الاختبارات في http://greenbytes.de/tech/tc2231/.

بالنسبة لي هذا حل المشكلة:

var result = new HttpResponseMessage(HttpStatusCode.OK)
{
   Content = new ByteArrayContent(data)
};

result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileNameStar = "foo-ä-€.html"
};

عندما أبدو إعلانًا على repsonse في Fiddler ، يمكنني رؤية أن اسم الملف قد تم ترميز العمال التلقائي باستخدام UTF-8:

مثال على استجابة Fiddler مع اسم ملف تعريف المحتوى المشفر باستخدام UTF-8

إذا نظرنا إلى قيمة رأس تحديد المحتوى ، يمكننا أن نرى أنه سيكون هو نفسه johannes geyer إجابته. الفرق الوحيد هو أنه لم يكن علينا القيام بتشفير أنفسنا ، فإن فئة ContentDispositionHeadervalue تعتني بذلك.

لقد استخدمت testcases لرأس Disposition على: http://greenbytes.de/tech/tc2231/ كما ذكر جوليان ريتشكي. يمكن العثور على معلومات حول فئة ContentDispositionHeadervalue على MSDN.

بالنسبة إلى ASP.NET Core (الإصدار 2 اعتبارًا من هذا المنشور) ، تم إهمال urlpathencode ، إليك كيفية تحقيق النتيجة المرجوة:

System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
   FileName = Uri.EscapeUriString(fileName),
   Inline = true  // false = prompt the user for downloading;  true = browser to try to show the file inline
};

Response.Headers.Add("Content-Disposition", cd.ToString());

أنا باستخدام Uri.EscapeUriString لتحويل جميع الشخصيات إلى تمثيلها السداسي عشري ، و string.Normalize لنموذج تطبيع Unicode C. (تم اختباره في ASP.NET MVC5 Framework 4.5)

    var contentDispositionHeader = new System.Net.Mime.ContentDisposition
    {
        Inline = false,
        FileName = Uri.EscapeUriString(Path.GetFileName(pathFile)).Normalize()
    };
    Response.Headers.Add("Content-Disposition", contentDispositionHeader.ToString());
    string mimeType = MimeMapping.GetMimeMapping(Server.MapPath(pathFile));
    return File(file, mimeType);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top