Question

J'ai téléchargé une classe HttpHandler qui concatène les fichiers JS en un seul fichier et continue d'ajouter les caractères & # 239; & # 187; & # 191; au début de chaque fichier concaténé .

Des idées sur ce qui cause cela? Se pourrait-il qu'une fois les fichiers traités, ils soient écrits dans le cache et que le cache le stocke / le rende?

Toute entrée serait grandement appréciée.

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; }
    }
}
Était-ce utile?

La solution

OK, j'ai débogué votre code.

Les marques de nomenclature apparaissent dans le flux source lorsque les fichiers sont lus à partir du disque:

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

Si vous lisez les fichiers correctement, vous pouvez vous en débarrasser.

Autres conseils

Les & # 239; & # 187; & # 191; les caractères sont les marqueurs de nomenclature UTF .

Il s’agit de la marque d'ordre d'octet (BOM) .

Ce sera au début de chaque fichier, mais votre éditeur l’ignorera ici. Quand ils sont concaténés, ils se retrouvent au milieu, vous les voyez donc.

Je pense qu'il s'agit du marque d'ordre des octets (BOM) pour les fichiers au format UTF-8. codage. Cette marque permet de déterminer dans quel encodage le fichier est stocké.

Si vous avez le contenu du fichier dans une chaîne, .Trim () supprimera le "BOM". assez facilement.

Vous ne pourrez peut-être pas faire cela, ou vous voudrez peut-être vouloir les espaces à la fin du fichier, mais c'est certainement une option.

Pour .js, les espaces ne sont pas significatifs, cela pourrait donc fonctionner.

Vérifiez la manière dont vos fichiers js sont codés et fournissent le même codage dans le code qui effectue la lecture et la concaténation. Ces deux caractères désignent généralement un unicode.

Ces caractères sont des nomenclatures UTF-8. Il ne semble pas qu'ils viennent du flux compressé. Il est plus probable qu'ils soient insérés dans le flux de réponses. Je suggère donc d'effacer la réponse avant de la manipuler:

context.Response.Clear();

Vous n'avez pas publié la solution réelle. Voici ma soulution. Sur la ligne où le fichier est lu en mémoire, j'ai trouvé une manière étrange de supprimer la nomenclature:

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

Et vous avez également besoin de cette fonction:

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

Nitech

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top