Skip to content

Instantly share code, notes, and snippets.

@niik
Created July 12, 2011 17:14
Show Gist options
  • Save niik/1078451 to your computer and use it in GitHub Desktop.
Save niik/1078451 to your computer and use it in GitHub Desktop.
ContentDispositionUtils
/*
* Copyright (c) 2011 Markus Olsson
* var mail = string.Join(".", new string[] {"j", "markus", "olsson"}) + string.Concat('@', "gmail.com");
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Net.Mime;
namespace freakcode.Utilities
{
public static class ContentDispositionUtils
{
// A bunch of characters most likely to be forbidden (or be troublesome to use) in a file system
private static char[] invalids = "<>:\"/\\|?*~".ToCharArray();
// We try to prevent theese characters from repeating in the resulting string.
private static char[] spacingCharacters = { ' ', '_', '-' };
/// <summary>
/// Normalizes the given file name removing diacritics and special characters so as to maximize
/// the compatibility with user agents regardless of system charsets. Note that this method does produce
/// a strictly compliant header since it will not quote the string if neccessary. Use the GetHeaderValue
/// in order to produce a proper header value for use directly with an HttpResponse. The return value
/// of this method can be used directly with the File* actionresults in ASP.NET MVC.
/// </summary>
/// <example>
/// Will convert "Übername / document.pdf" to "Ubername document.pdf" and "c:\foobar.pdf" to "c_foobar.pdf"
/// </example>
/// <exception cref="ArgumentNullException">fileName was null</exception>
/// <exception cref="ArgumentException">fileName contained invalid Unicode characters.</exception>
public static string NormalizeFileName(string fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (fileName.Length == 0)
return string.Empty;
// Normalize string in order to remove diacritics. This will convert
// the string into a fully canonical form; ie Åäö will be converted to A°a¨o¨
char[] normalized = fileName.Normalize(NormalizationForm.FormD).ToCharArray();
// Set up a buffer for our return string that is at most (in case there's no diacritics and no forbidden characters)
// the same length as our normalized string.
char[] buf = new char[normalized.Length];
int p = 0;
for (int i = 0; i < normalized.Length; i++)
{
char c = normalized[i];
// Remove all non spacing marks (ie modifiers to base characters, umlauts and such);
if (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.NonSpacingMark)
continue;
// Strip special characters and commonly forbidden file system characters
if (c < 32 || c > 126 || invalids.Contains(c))
c = '_';
// Prevent repeating spacing characters
if (p != 0 && spacingCharacters.Contains(c) && spacingCharacters.Contains(buf[p - 1]))
continue;
buf[p++] = c;
}
return new string(buf, 0, p);
}
/// <summary>
/// Returns a content-disposition attachment header value with a filename parameter containing
/// a normalized form of the provided filename (see NormalizeFileName for more information).
/// </summary>
/// <exception cref="ArgumentNullException">fileName was null</exception>
/// <exception cref="ArgumentException">fileName contained invalid Unicode characters.</exception>
public static string GetHeaderValue(string fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
var header = new ContentDisposition
{
FileName = NormalizeFileName(fileName)
};
return header.ToString();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment