/// <summary> /// Calculates an MD5 hash for a specified byte range of the file specified by <paramref name="fileInfo" /> /// </summary> /// <param name="fileInfo">A <see cref="FileInfo" /> object specifying the file containing the content for which we're calculating the hash.</param> /// <returns>A string containing an MD5 hash.</returns> public string GetHash(FileInfo fileInfo) { using (var stream = RetryableFileOpener.OpenFileStream(fileInfo, 5, FileMode.Open, FileAccess.Read, FileShare.Read)) { return(GetHash(stream)); } }
/// <summary> /// Calculates an MD5 hash for a specified byte range of the file specified by <paramref name="fileInfo" /> /// </summary> /// <param name="fileInfo">A <see cref="FileInfo" /> object specifying the file containing the content for which we're calculating the hash.</param> /// <returns>A string containing an MD5 hash.</returns> public string GetHash(FileInfo fileInfo) { using (var stream = RetryableFileOpener.OpenFileStream(fileInfo, 5, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Now that we have a byte array we can ask the CSP to hash it var md5 = new MD5CryptoServiceProvider(); var hashBytes = md5.ComputeHash(stream); return(ByteArrayToString(hashBytes)); } }
/// <summary> /// Transmit stream to browser. /// </summary> /// <param name="retryableFileOpener"></param> /// <param name="response">The <see cref="HttpResponse" /> of the current HTTP request.</param> /// <param name="file"></param> /// <param name="bufferSize">The buffer size to use when transmitting file to browser.</param> public virtual void TransmitFile(IRetryableFileOpener retryableFileOpener, HttpResponseBase response, FileInfo file, int bufferSize) { using (var stream = retryableFileOpener.OpenFileStream(file, 5, FileMode.Open, FileAccess.Read, FileShare.Read)) { var buffer = new byte[bufferSize]; var readCount = 0; while ((readCount = stream.Read(buffer, 0, bufferSize)) > 0) { response.OutputStream.Write(buffer, 0, readCount); } } }
/// <summary> /// Get sprites for image files. /// </summary> /// <param name="files">The component images for the sprite.</param> /// <returns>A list of css sprites</returns> public virtual List <SpriteElement> ProcessFiles(IEnumerable <ImageFile> files) { var spriteElements = new List <SpriteElement>(); foreach (var file in files) { var filePath = new Uri(PathProvider.MapPath(file.FilePath)).LocalPath; var fileInfo = new FileInfo(filePath); using (var reader = RetryableFileOpener.OpenFileStream(fileInfo, 5, FileMode.Open, FileAccess.Read, FileShare.Read)) { var spriteElement = new SpriteElement(file.Name, reader); spriteElements.Add(spriteElement); } } return(spriteElements); }
/// <summary> /// Transmit stream range to browser. /// </summary> /// <param name="retryableFileOpener"></param> /// <param name="response">The <see cref="HttpResponse" /> of the current HTTP request.</param> /// <param name="file"></param> /// <param name="bufferSize">The buffer size to use when transmitting file to browser.</param> /// <param name="offset">Start range</param> /// <param name="length">End range</param> public virtual void TransmitFile(IRetryableFileOpener retryableFileOpener, HttpResponseBase response, FileInfo file, long bufferSize, long offset, long length) { using (var stream = retryableFileOpener.OpenFileStream(file, 5, FileMode.Open, FileAccess.Read, FileShare.Read)) { stream.Seek(offset, SeekOrigin.Begin); var buffer = new byte[bufferSize]; while (length > 0) { var lengthOfReadChunk = stream.Read(buffer, 0, (int)Math.Min(bufferSize, length)); // Write the data to the current output stream. response.OutputStream.Write(buffer, 0, lengthOfReadChunk); // Reduce BytesToRead length -= lengthOfReadChunk; } } }
/// <summary> /// Read a files contents into a stream /// </summary> /// <param name="compressionType">The compression type to use.</param> /// <param name="stream">The stream to write to.</param> private void GetEntityData(ResponseCompressionType compressionType, Stream stream) { using (var outputStream = (compressionType == ResponseCompressionType.None ? stream : (compressionType == ResponseCompressionType.GZip ? (Stream) new GZipStream(stream, CompressionMode.Compress, true) : (Stream) new DeflateStream(stream, CompressionMode.Compress)))) { // We can compress and cache this file using (var fileStream = RetryableFileOpener.OpenFileStream(FileInfo, 5, FileMode.Open, FileAccess.Read, FileShare.Read)) { var bufferSize = Convert.ToInt32(Math.Min(FileInfo.Length, BufferSize)); var buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = fileStream.Read(buffer, 0, bufferSize)) > 0) { outputStream.Write(buffer, 0, bytesRead); } } outputStream.Flush(); } }
/// <summary> /// Save stream to file. /// </summary> /// <param name="outputStream">The stream to save.</param> /// <param name="outputPath">The path for the file to save.</param> public virtual string SaveContentsToFile(Stream outputStream, FileInfo outputPath) { var etag = string.Empty; //We might be competing with the web server for the output file, so try to overwrite it at regular intervals using (var outputFile = RetryableFileOpener.OpenFileStream(outputPath, 5, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { var overwrite = true; if (outputFile.Length > 0) { etag = Hasher.CalculateMd5Etag(outputStream); var outputFileHash = Hasher.CalculateMd5Etag(outputFile); overwrite = (etag != outputFileHash); } if (overwrite) { outputStream.Seek(0, SeekOrigin.Begin); outputFile.SetLength(outputStream.Length); //Truncate current file outputFile.Seek(0, SeekOrigin.Begin); var bufferSize = Convert.ToInt32(Math.Min(outputStream.Length, BufferSize)); var buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = outputStream.Read(buffer, 0, bufferSize)) > 0) { outputFile.Write(buffer, 0, bytesRead); } outputFile.Flush(); } } return(etag); }
/// <summary> /// Compress the js files and store them in the specified js file. /// </summary> /// <param name="outputPath">The path for the crushed js file.</param> /// <param name="files">The js files to be crushed.</param> private static void ProcessFiles(string outputPath, IEnumerable <JsFile> files) { var uncompressedContents = new StringBuilder(); var toBeCompressedContents = new StringBuilder(); foreach (var file in files) { var fileInfo = new FileInfo(HostingEnvironment.MapPath(file.FilePath)); var fileContents = _retryableFileOpener.ReadAllText(fileInfo); switch (file.CompressionType) { case JsCompressionType.None: uncompressedContents.AppendLine(fileContents); break; case JsCompressionType.Min: toBeCompressedContents.AppendLine(fileContents); break; } } var uncompressedContent = uncompressedContents.ToString(); var compressedContent = toBeCompressedContents.ToString(); if (!string.IsNullOrEmpty(compressedContent)) { compressedContent = JavaScriptCompressor.Compress(compressedContent); } using (var writer = new MemoryStream()) { var uniEncoding = Encoding.Default; if (!string.IsNullOrEmpty(uncompressedContent)) { writer.Write(uniEncoding.GetBytes(uncompressedContent), 0, uniEncoding.GetByteCount(uncompressedContent)); } if (!string.IsNullOrEmpty(compressedContent)) { writer.Write(uniEncoding.GetBytes(compressedContent), 0, uniEncoding.GetByteCount(compressedContent)); } //We might be competing with the web server for the output file, so try to overwrite it at regular intervals using (var outputFile = _retryableFileOpener.OpenFileStream(new FileInfo(HostingEnvironment.MapPath(outputPath)), 5, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { var overwrite = true; if (outputFile.Length > 0) { var newOutputFileHash = _hasher.CalculateMd5Etag(writer); var outputFileHash = _hasher.CalculateMd5Etag(outputFile); overwrite = (newOutputFileHash != outputFileHash); } if (overwrite) { writer.Seek(0, SeekOrigin.Begin); outputFile.SetLength(writer.Length); //Truncate current file outputFile.Seek(0, SeekOrigin.Begin); var bufferSize = Convert.ToInt32(Math.Min(writer.Length, BufferSize)); var buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = writer.Read(buffer, 0, bufferSize)) > 0) { outputFile.Write(buffer, 0, bytesRead); } outputFile.Flush(); } } } }
/// <summary> /// Compress the css files and store them in the specified css file. /// </summary> /// <param name="outputPath">The path for the crushed css file.</param> /// <param name="files">The css files to be crushed.</param> private static void ProcessFiles(string outputPath, IEnumerable <CssFile> files) { outputPath = HostingEnvironment.MapPath(outputPath); var uncompressedContents = new StringBuilder(); var toBeStockYuiCompressedContents = new StringBuilder(); var toBeMichaelAshRegexCompressedContents = new StringBuilder(); var toBeHybridCompressedContents = new StringBuilder(); foreach (var file in files) { var fileInfo = new FileInfo(HostingEnvironment.MapPath(file.FilePath)); var fileContents = _retryableFileOpener.ReadAllText(fileInfo); var fileName = fileInfo.Name.ToLower(); if (fileName.EndsWith(".less") || fileName.EndsWith(".less.css")) { fileContents = ProcessDotLess(fileContents); } fileContents = _cssPathRewriter.RewriteCssPaths(outputPath, fileInfo.FullName, fileContents); switch (file.CompressionType) { case CssCompressionType.None: uncompressedContents.AppendLine(fileContents); break; case CssCompressionType.StockYuiCompressor: toBeStockYuiCompressedContents.AppendLine(fileContents); break; case CssCompressionType.MichaelAshRegexEnhancements: toBeMichaelAshRegexCompressedContents.AppendLine(fileContents); break; case CssCompressionType.Hybrid: toBeHybridCompressedContents.AppendLine(fileContents); break; } } var uncompressedContent = uncompressedContents.ToString(); var stockYuiCompressedCompressedContent = toBeStockYuiCompressedContents.ToString(); var michaelAshRegexCompressedContent = toBeMichaelAshRegexCompressedContents.ToString(); var hybridCompressedContent = toBeHybridCompressedContents.ToString(); if (!string.IsNullOrEmpty(stockYuiCompressedCompressedContent)) { stockYuiCompressedCompressedContent = CssCompressor.Compress(stockYuiCompressedCompressedContent, 0, Yahoo.Yui.Compressor.CssCompressionType.StockYuiCompressor); } if (!string.IsNullOrEmpty(michaelAshRegexCompressedContent)) { michaelAshRegexCompressedContent = CssCompressor.Compress(michaelAshRegexCompressedContent, 0, Yahoo.Yui.Compressor.CssCompressionType.MichaelAshRegexEnhancements); } if (!string.IsNullOrEmpty(hybridCompressedContent)) { hybridCompressedContent = CssCompressor.Compress(hybridCompressedContent, 0, Yahoo.Yui.Compressor.CssCompressionType.Hybrid); } using (var writer = new MemoryStream()) { var uniEncoding = Encoding.Default; if (!string.IsNullOrEmpty(uncompressedContent)) { writer.Write(uniEncoding.GetBytes(uncompressedContent), 0, uniEncoding.GetByteCount(uncompressedContent)); } if (!string.IsNullOrEmpty(stockYuiCompressedCompressedContent)) { writer.Write(uniEncoding.GetBytes(stockYuiCompressedCompressedContent), 0, uniEncoding.GetByteCount(stockYuiCompressedCompressedContent)); } if (!string.IsNullOrEmpty(michaelAshRegexCompressedContent)) { writer.Write(uniEncoding.GetBytes(michaelAshRegexCompressedContent), 0, uniEncoding.GetByteCount(michaelAshRegexCompressedContent)); } if (!string.IsNullOrEmpty(hybridCompressedContent)) { writer.Write(uniEncoding.GetBytes(hybridCompressedContent), 0, uniEncoding.GetByteCount(hybridCompressedContent)); } //We might be competing with the web server for the output file, so try to overwrite it at regular intervals using (var outputFile = _retryableFileOpener.OpenFileStream(new FileInfo(outputPath), 5, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { var overwrite = true; if (outputFile.Length > 0) { var newOutputFileHash = _hasher.CalculateMd5Etag(writer); var outputFileHash = _hasher.CalculateMd5Etag(outputFile); overwrite = (newOutputFileHash != outputFileHash); } if (overwrite) { writer.Seek(0, SeekOrigin.Begin); outputFile.SetLength(writer.Length); //Truncate current file outputFile.Seek(0, SeekOrigin.Begin); var bufferSize = Convert.ToInt32(Math.Min(writer.Length, BufferSize)); var buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = writer.Read(buffer, 0, bufferSize)) > 0) { outputFile.Write(buffer, 0, bytesRead); } outputFile.Flush(); } } } }