Current version of CS use Content-disposition filename header field to set correct filename during download.
This work correctly on IE 7/8 and not work on all other browsers.
This browser not UrlEncode filename field from Content-disposition field.
Simply change next httphandlers (web.config) to support national filenames.
<system.web> ... <httpHandlers> ... <add verb="GET" path="cfs-file.ashx" type="CustomCSHandlers.FileHttpHandler, CustomCSHandlers" /> <add verb="GET" path="cfs-filesystemfile.ashx" type="CustomCSHandlers.FileSystemFileStorageHttpHandler, CustomCSHandlers" /> ... </httpHandlers> ... </system.web>
Create C# class library project CustomCSHandlers and add 2 files.
1.FileHttpHandler.cs
using System; using System.Collections.Generic; using System.Text; using System.Web; using CommunityServer.Components; namespace CustomCSHandlers { public class FileHttpHandler : IHttpHandler { // Requested URLS are in the format: .../__key/filestorekey/path/filename public bool IsReusable { get { return true; } } public void ProcessRequest(HttpContext context) { CSContext.Current.AllowTokenRequests(false); ICentralizedFile file = CentralizedFileStorageProvider.GetCentralizedFileByUrl(context.Request.Url.ToString()); if (file != null) { context.Response.Cache.SetAllowResponseInBrowserHistory(true); context.Response.Cache.SetValidUntilExpires(true); context.Response.Cache.SetExpires(DateTime.Now.AddDays(1)); context.Response.Cache.SetLastModified(DateTime.Now); if (CentralizedFileStorageProvider.HasAccessValidator(file.FileStoreKey)) context.Response.Cache.SetCacheability(HttpCacheability.Private); else context.Response.Cache.SetCacheability(HttpCacheability.Public); if (CentralizedFileStorageProvider.CurrentUserHasAccess(file.FileStoreKey, file.Path, file.FileName)) { string path = file.GetDownloadUrl(); int i; if ((i = path.LastIndexOf("/")) > 0) { string filename = Globals.UrlDecodeFileComponent(path.Substring(i + 1)); path = path.Substring(0, i + 1) + "N$/" + filename; } context.Response.RedirectLocation = Globals.FullPath(path); context.Response.StatusCode = 301; } else context.Response.StatusCode = 403; } else context.Response.StatusCode = 404; } } }
2. FileSystemFileStorageHttpHandler.cs
using System; using System.Collections.Generic; using System.Text; using CommunityServer.Components; using System.IO; using System.Web; namespace CustomCSHandlers { public class FileSystemFileStorageHttpHandler : IHttpHandler { // Requested URLS are in the format: ...__key/[filestorekey]/[path]/[filename] public bool IsReusable { get { return true; } } protected CommunityServer.Components.FileSystemFileStorageFile GetFileFromPath(string path) { int index = path.IndexOf("__key/"); if (index < 0) return null; path = path.Substring(index + 6); index = path.IndexOf('/'); if (index < 0) return null; string fileStoreKey = path.Substring(0, index); index = path.LastIndexOf('/'); if (index < 0) return null; string fileName = path.Substring(index + 1); if (path.Length - (fileStoreKey.Length + fileName.Length + 2) <= 0) path = string.Empty; else path = path.Substring(fileStoreKey.Length + 1, path.Length - (fileStoreKey.Length + fileName.Length + 2)); fileStoreKey = Globals.UrlDecodePathComponent(fileStoreKey); if (path.EndsWith("/N$"))path = path.Substring(0, path.Length - 3);
else if (path == "N$")
path = path.Substring(0, path.Length - 2); else fileName = Globals.UrlDecodeFileComponent(fileName); path = Globals.UrlDecodePathComponent(path); if (string.IsNullOrEmpty(fileStoreKey) || string.IsNullOrEmpty(fileName)) return null; CommunityServer.Components.FileSystemFileStorageProvider fileProvider = CentralizedFileStorageProvider.Instance(fileStoreKey) as CommunityServer.Components.FileSystemFileStorageProvider; if (fileProvider != null) return fileProvider.GetFile(path, fileName) as CommunityServer.Components.FileSystemFileStorageFile; else return null; } public void ProcessRequest(HttpContext context) { CSContext.Current.AllowTokenRequests(false); CommunityServer.Components.FileSystemFileStorageFile file = GetFileFromPath(context.Request.Path); if (file == null) { context.Response.StatusCode = 404; return; } DateTime lastModified = (new FileInfo(file.FullLocalPath)).LastWriteTime; DateTime currentLastModifiedDate = DateTime.MinValue; #region If-Modified-Since DateTime.TryParse(context.Request.Headers["If-Modified-Since"] ?? "", out currentLastModifiedDate); if (Math.Abs(((TimeSpan)lastModified.ToUniversalTime().Subtract(currentLastModifiedDate.ToUniversalTime())).TotalSeconds) <= 1) { context.Response.StatusCode = 304; context.Response.Status = "304 Not Modified"; return; } #endregion #region If-None-Match (ETag) long eTag = 0; if (long.TryParse(context.Request.Headers["If-None-Match"] ?? "", out eTag)) { currentLastModifiedDate = new DateTime(eTag); if (lastModified == currentLastModifiedDate) { context.Response.StatusCode = 304; context.Response.Status = "304 Not Modified"; return; } } #endregion if (!CentralizedFileStorageProvider.CurrentUserHasAccess(file.FileStoreKey, file.Path, file.FileName)) { context.Response.StatusCode = 403; return; } context.Response.ContentType = CommunityServer.Configuration.MimeTypeConfiguration.GetMimeType(file.FileName); context.Response.Cache.SetAllowResponseInBrowserHistory(true); context.Response.Cache.SetLastModified(lastModified.ToUniversalTime()); context.Response.Cache.SetETag(lastModified.Ticks.ToString()); if (!CentralizedFileStorageProvider.HasAccessValidator(file.FileStoreKey)) context.Response.Cache.SetCacheability(HttpCacheability.Public); else context.Response.Cache.SetCacheability(HttpCacheability.Private); string disposition; if (context.Response.ContentType == "application/pdf" || context.Response.ContentType == "application/octet-stream") disposition = "attachment"; else disposition = "inline"; if (context.Request.Browser.Browser.IndexOf("Netscape") != -1) context.Response.AddHeader("Content-disposition", disposition + "; filename*0*=" + context.Server.UrlEncode(file.FileName).Replace("+", "%20") + ""); else { context.Response.AddHeader("Content-disposition", disposition); // filename=" + context.Server.UrlEncode(file.FileName).Replace("+", "%20") + ""); } // Send files stored on UNC paths explicitly to avoid a bug with TransmitFile. if (!file.FullLocalPath.StartsWith("\\")) context.Response.TransmitFile(file.FullLocalPath); else { context.Response.AddHeader("Content-Length", file.ContentLength.ToString("0")); using (Stream s = new FileStream(file.FullLocalPath, FileMode.Open, FileAccess.Read)) { context.Response.Buffer = false; context.Response.BufferOutput = false; try { byte[] buffer = new byte[64 * 1024]; int read; while ((read = s.Read(buffer, 0, buffer.Length)) > 0) { if (!context.Response.IsClientConnected) break; context.Response.OutputStream.Write(buffer, 0, read); context.Response.OutputStream.Flush(); } } catch (HttpException) { } catch (Exception ex) { new CSException(CSExceptionType.UnknownError, "FileSystemFileStorageFile", ex).Log(); } context.Response.Flush(); context.Response.Close(); s.Close(); } } } } }
add CustomCSHandlers.dll to bin folder.
0 comment(s) so far