문제

JS 파일을 하나의 파일로 연결하는 httphandler 클래스를 다운로드했으며 계속 추가합니다.  각 파일의 시작 부분에 문자는 연결됩니다.

이것에 대한 원인에 대한 아이디어가 있습니까? 처리 된 파일이 캐시에 기록되어 있으며 캐시가 저장/렌더링하는 방식일까요?

모든 입력은 크게 감사 할 것입니다.

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; }
    }
}
도움이 되었습니까?

해결책

좋아, 코드를 디버깅했습니다.

파일을 디스크에서 읽을 때 BOM 마크가 소스 스트림에 나타납니다.

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

파일을 올바르게 읽으면 마크를 제거 할 수 있습니다.

다른 팁

 문자는입니다 UTF BOM 마커.

그것의 UTF 바이트 주문 마크 (BOM).

각 파일의 시작 부분에 있지만 편집기는이 파일을 무시합니다. 동의하면 그들은 중간에 끝납니다. 그래서 당신은 그들을 볼 수 있습니다.

나는 이것이 것이라고 생각한다 바이트 주문 마크 (BOM) UTF-8 인코딩이있는 파일 용. 이 마크를 사용하면 파일을 인코딩하는 내용을 결정할 수 있습니다.

문자열에 파일의 내용이있는 경우 .trim ()은 "bom"을 매우 손으로 꺼냅니다.

당신은 그렇게하지 않을 수도 있고, 그렇지 않을 수도 있습니다. 원하다 파일 끝의 공백은 확실히 옵션입니다.

.js whitespace의 경우 중요하지 않으므로 작동 할 수 있습니다.

JS 파일이 인코딩 된 방법을 확인하고 읽기 및 연결을 수행하는 코드에서 동일한 인코딩을 제공하십시오. 이 두 문자는 일반적으로 유니 코드를 가리 킵니다.

그 캐릭터는 UTF-8 BOM입니다. 그들이 gzipped 스트림에서 오는 것처럼 보이지 않습니다. 응답 스트림에 삽입 될 가능성이 높으므로 응답 작업을 수행하기 전에 응답을 지우는 것이 좋습니다.

context.Response.Clear();

당신은 실제 솔루션이 무엇인지 게시하지 않았습니다. 여기 내 영혼이 있습니다. 파일을 메모리로 읽는 줄에서 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);
} 

니 테크

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top