سؤال

ولقد قمت بتحميل فئة HttpHandler أن يسلسل ملفات JS في ملف واحد، وأنها تحتفظ إلحاق الأحرف  في بداية كل تودعه يسلسل.

وأي أفكار حول ما يسبب هذا؟ هل يمكن أن تكون onces الملفات معالجتها تتم كتابتها إلى ذاكرة التخزين المؤقت وهذه هي الطريقة التي ذاكرة التخزين المؤقت وتخزين / تقديم ذلك؟

وأي مدخلات سيكون موضع تقدير كبير.

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; }
    }
}
هل كانت مفيدة؟

المحلول

وOK، لقد تصحيحه التعليمات البرمجية.

وتظهر علامات BOM في مجرى المصدر عندما يتم قراءة الملفات من القرص:

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

إذا كنت تقرأ الملفات بشكل صحيح، يمكنك التخلص من علامات.

نصائح أخرى

ووï »¿الأحرف هي UTF BOM .

علامة ترتيب البايت (BOM) .

وسيكون في بداية كل ملف، ولكن المحرر الخاص بك تجاهلها هناك. عند متصلا أنهم في نهاية المطاف في الوسط، لذلك تراهم.

وأعتقد أن هذا هو علامة ترتيب البايت (BOM) للحصول على الملفات مع UTF-8 التشفير. هذه العلامة يسمح لتحديد في ما ترميز ملف يتم تخزينها.

إذا كان لديك محتويات الملف في سلسلة، .Trim () ولوب قبالة "BOM" بشكل ملائم تماما.

وأنت قد لا تكون قادرة على القيام بذلك، أو قد <م> تريد وبيضاء في نهايات الملف، لكنه بالتأكيد خيارا.

لبيضاء شبيبة ليست كبيرة، لذلك هذا يمكن أن تنجح.

والتحقق من كيفية يتم ترميز الملفات شبيبة وتقديم نفس الترميز في التعليمات البرمجية التي لا القراءة وسلسلة. عادة ما تشير هاتين الشخصيتين إلى يونيكود.

وهذه الشخصيات هي UTF-8 BOM. لا يبدو وكأنهم القادمة من تيار مضغوط بطريقة gzip. لكن على الأرجح يتم إدراجها إلى دفق استجابة، لذلك أود أن أقترح إزالة الاستجابة قبل العمل معها:

context.Response.Clear();

وأنت لم ينشئ ما هو الحل الفعلي. وهنا قال لي soulution. على السطر حيث يقرأ الملف في الذاكرة، وجدت نوعا من طريقة غريبة لإزالة 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);
} 

وNitech

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top