пʼятниця, 4 грудня 2009 р.

Кроссбраузерный "Content-Disposition" "attachment; filename"

Наверняка всем знаком заголовок "Content-Disposition" со значением "attachment; filename".  Казалось бы, что может быть проще. Но оказывается и здесь есть свои нюансы. Для меня эти нюансы вылились в то, что при тестировании нормально filename определяла только Opera. Ослик сохранял файл с именем вида B_0JzQsNC70YzRh9C40LrQ. FireFox при сохранении файлов в именах которых содержатся пробелы, сохранял файл с частъю имени до первого пробела.
Впрочем проблемы возникали не только у меня:
1) http://softwaremaniacs.org/forum/django/14097/
2) http://sql.ru/forum/actualthread.aspx?tid=584761
3) http://www.gotdotnet.ru/forums/4/61117/294999/#post294999
но работающего решения так и не было найдено.
После более детального изучения проблемы и "доработки напильником" выяснилось, что IE понимает не ASCII имена файлов только в формате URL Encoding. А FireFox единственный который нуждается в обрамлении имени файла двойными ковычками. Таким образом получили работающий кроссбраузреный attachment; filename. Код выглядит следующим образом:


                string fileName = fileInfo.Name;
                if (IsIE(Request.Browser))
                {
                    fileName = Server.UrlEncode(fileInfo.Name);
                    if (fileName != null) fileName = fileName.Replace(@"+", @"%20");
                }

                Response.ContentType = "application/octet-stream";
                Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");

Работает для IE8, FF3.5.5, Opera 10.10

2 коментарі:

  1. как бы получить за одно код функции IsIE?

    ВідповістиВидалити
    Відповіді
    1. protected static bool IsIE(HttpBrowserCapabilities browser)
      {
      bool isIE = Utils.GetBrowserType(browser) == "IE";
      return isIE;
      }

      public static string GetBrowserType(HttpBrowserCapabilities browser)
      {
      string result = "";
      if (IsContaineType(browser, "mozil"))
      result = "Mozilla";
      if (IsContaineType(browser, "opera"))
      result = "Opera";
      if (IsContaineType(browser, "ie"))
      result = "IE";
      if (IsContaineType(browser, "netscape"))
      result = "Mozilla";
      if (IsContaineType(browser, "internet"))
      result = "IE";
      if (IsContaineType(browser, "safari"))
      result = "Safari";
      return result;
      }

      private static bool IsContaineType(HttpBrowserCapabilities browser, string type)
      {
      HttpBrowserCapabilities bc = browser;
      bool result = false;
      foreach (string bt in bc.Browsers)
      {
      result = bt.ToLower().StartsWith(type);
      if (result) break;
      }
      return result;
      }

      Видалити