代码之家  ›  专栏  ›  技术社区  ›  IEnumerator

_»?附加到每个文件开头的字符

  •  8
  • IEnumerator  · 技术社区  · 17 年前

    我下载了一个httphandler类,它将JS文件连接到一个文件中,并不断附加  它连接的每个文件开头的字符。

    你知道是什么引起的吗?一旦处理了文件,它们就被写入缓存,这就是缓存存储/呈现它的方式吗?

    任何投入都将受到极大的赞赏。

    using System;
    using System.Net;
    using System.IO;
    using System.IO.Compression;
    using System.Text;
    using System.Configuration;
    using System.Web;
    
    public class HttpCombiner : IHttpHandler {
    
        private const bool DO_GZIP = false;
        private readonly static TimeSpan CACHE_DURATION = TimeSpan.FromDays(30);
    
        public void ProcessRequest (HttpContext context) {
    
            HttpRequest request = context.Request;
    
            // Read setName, contentType and version. All are required. They are
            // used as cache key
            string setName = request["s"] ?? string.Empty;
            string contentType = request["t"] ?? string.Empty;
            string version = request["v"] ?? string.Empty;
    
            // Decide if browser supports compressed response
            bool isCompressed = DO_GZIP && this.CanGZip(context.Request);
    
            // Response is written as UTF8 encoding. If you are using languages
            // like Arabic, you should change this to proper encoding 
            UTF8Encoding encoding = new UTF8Encoding(false);
    
            // If the set has already been cached, write the response directly
            // from cache. Otherwise generate the response and cache it
            if (!this.WriteFromCache(context, setName, version, isCompressed,
                contentType))
            {
                using (MemoryStream memoryStream = new MemoryStream(5000))
                {
                    // Decide regular stream or GZipStream based on whether the
                    // response can be cached or not
                    using (Stream writer = isCompressed
                        ? (Stream)(new GZipStream(memoryStream,
                            CompressionMode.Compress))
                        : memoryStream)
                    {
                        // Load the files defined in <appSettings> and process
                        // each file
                        string setDefinition = System.Configuration
                            .ConfigurationManager.AppSettings[setName] ?? "";
                        string[] fileNames = setDefinition.Split(
                            new char[] { ',' }, 
                            StringSplitOptions.RemoveEmptyEntries);
    
                        foreach (string fileName in fileNames)
                        {
                            byte[] fileBytes = this.GetFileBytes(
                                context, fileName.Trim(), encoding);
                            writer.Write(fileBytes, 0, fileBytes.Length);
                        }
    
                        writer.Close();
                    }
    
                    // Cache the combined response so that it can be directly
                    // written in subsequent calls 
                    byte[] responseBytes = memoryStream.ToArray();
                    context.Cache.Insert(
                        GetCacheKey(setName, version, isCompressed),
                        responseBytes, null,
                        System.Web.Caching.Cache.NoAbsoluteExpiration,
                        CACHE_DURATION);
    
                    // Generate the response
                    this.WriteBytes(responseBytes, context, isCompressed,
                        contentType);
                }
            }
        }
    
        private byte[] GetFileBytes(HttpContext context, string virtualPath,
            Encoding encoding)
        {
            if (virtualPath.StartsWith("http://",
                StringComparison.InvariantCultureIgnoreCase))
            {
                using (WebClient client = new WebClient())
                {
                    return client.DownloadData(virtualPath);
                }
            }
            else
            {
                string physicalPath = context.Server.MapPath(virtualPath);
                byte[] bytes = File.ReadAllBytes(physicalPath);
                // TODO: Convert unicode files to specified encoding.
                // For now, assuming files are either ASCII or UTF8
                return bytes;
            }
        }
    
        private bool WriteFromCache(HttpContext context, string setName,
            string version, bool isCompressed, string contentType)
        {
            byte[] responseBytes = context.Cache[GetCacheKey(setName, version,
                isCompressed)] as byte[];
    
            if (null == responseBytes || 0 == responseBytes.Length) return false;
    
            this.WriteBytes(responseBytes, context, isCompressed, contentType);
            return true;
        }
    
        private void WriteBytes(byte[] bytes, HttpContext context, 
            bool isCompressed, string contentType)
        {
            HttpResponse response = context.Response;
    
            response.AppendHeader("Content-Length", bytes.Length.ToString());
            response.ContentType = contentType;
            if (isCompressed)
                response.AppendHeader("Content-Encoding", "gzip");
    
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetExpires(DateTime.Now.Add(CACHE_DURATION));
            context.Response.Cache.SetMaxAge(CACHE_DURATION);
            context.Response.Cache.AppendCacheExtension(
                "must-revalidate, proxy-revalidate");
    
            response.OutputStream.Write(bytes, 0, bytes.Length);
            response.Flush();
        }
    
        private bool CanGZip(HttpRequest request)
        {
            string acceptEncoding = request.Headers["Accept-Encoding"];
            if (!string.IsNullOrEmpty(acceptEncoding) &&
                 (acceptEncoding.Contains("gzip")
                     || acceptEncoding.Contains("deflate")))
                return true;
            return false;
        }
    
        private string GetCacheKey(string setName, string version,
            bool isCompressed)
        {
            return "HttpCombiner." + setName + "." + version + "." + isCompressed;
        }
    
        public bool IsReusable
        {
            get { return true; }
        }
    }
    
    8 回复  |  直到 14 年前
        1
  •  5
  •   DreamSonic    17 年前

    好的,我已经调试了你的代码。

    从磁盘读取文件时,源流中会出现物料清单标记:

    byte[] bytes = File.ReadAllBytes(physicalPath);
    // TODO: Convert unicode files to specified encoding. For now, assuming
    // files are either ASCII or UTF8
    

    如果你正确地阅读了这些文件,你就可以去掉这些标记。

        2
  •  21
  •   Stefan    17 年前

    角色是 UTF BOM markers .

        3
  •  7
  •   Greg    17 年前

    它的UTF Byte Order Mark (BOM) .

    它将在每个文件的开头,但您的编辑器将在那里忽略它们。当它们连接在一起时,会在中间结束,所以您可以看到它们。

        4
  •  6
  •   M4N    17 年前

    我想这是 Byte Order Mark (BOM) 对于使用UTF-8编码的文件。此标记允许确定存储文件的编码方式。

        5
  •  3
  •   Broam    16 年前

    如果文件的内容在字符串中,.trim()将非常容易地去掉“bom”。

    你可能做不到,或者 希望 文件末尾的空白,但它当然是一个选项。

    对于.js来说,空白空间并不重要,所以这可以工作。

        6
  •  2
  •   Boris Pavlović    17 年前

    检查JS文件是如何编码的,并在执行读取和连接的代码中提供相同的编码。这两个字符通常指向Unicode。

        7
  •  2
  •   DreamSonic    17 年前

    这些字符是UTF-8BOM。它们看起来不像是从gzipped流来的。它们更可能被插入到响应流中,因此我建议在处理之前清除响应:

    context.Response.Clear();
    
        8
  •  2
  •   nitech    17 年前

    你没有公布实际的解决方案。这是我的灵魂。在它将文件读取到内存的那一行,我发现了一种奇怪的方法来删除BOM:

    byte[] bytes = File.ReadAllBytes(physicalPath);
    String ss = new StreamReader(new MemoryStream(bytes), true).ReadToEnd();
    byte[] b = StrToByteArray(ss);
    return b;  
    

    你还需要这个功能:

    public static byte[] StrToByteArray(string str)
    {
        System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
        return encoding.GetBytes(str);
    } 
    

    硝酸甘油