文字は、各ファイルの先頭に追加します
-
19-08-2019 - |
質問
私は1つのファイルにJSファイルを連結し、それが連結し、各ファイルの先頭に
文字を追加し続けるのHttpHandlerクラスをダウンロードします。
これを引き起こしているものを上の任意のアイデア?それはそれは、彼らがキャッシュに書き込まれ、キャッシュが保存されてどのようにそれをレンダリング/です処理されたファイルを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されます。
そのUTF バイトオーダーマーク(BOM)にます。
これは、各ファイルの先頭になりますが、あなたのエディタがあり、それらを無視します。連結されたとき、彼らは途中で終わるので、あなたはそれらを参照してください。
私は、これはUTF-8でのファイルのためのバイトオーダーマーク(BOM)のだと思いますエンコーディング。このマークが保存されているどのファイルをコードに決定することができます。
、.Trim()は非常に手際よく「BOM」を切り落とすされます。
あなたはそれを行うことができない場合があります。または、のファイルの端での空白場合がありますが、それは確かにオプションです。
の.js空白の場合は重要ではありませんので、これは仕事ができるます。
あなたのjsファイルがエンコードされているかチェックして、読書や連結を行うコードで同じエンコーディングを提供します。これらの2つの文字は、通常、ユニコードを指します。
これらの文字は、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