Skip to content

Commit 1937f4c

Browse files
committed
Bug fixes, add simulation.
1 parent 57bb798 commit 1937f4c

File tree

6 files changed

+74
-51
lines changed

6 files changed

+74
-51
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
<ProjectGuid>{84285BB3-2556-45F3-965F-4667855A6EB6}</ProjectGuid>
88
<OutputType>Exe</OutputType>
99
<AppDesignerFolder>Properties</AppDesignerFolder>
10-
<RootNamespace>BlobGZipUtility</RootNamespace>
11-
<AssemblyName>BlobGZipUtility</AssemblyName>
10+
<RootNamespace>ASGE</RootNamespace>
11+
<AssemblyName>ASGE</AssemblyName>
1212
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
1313
<FileAlignment>512</FileAlignment>
1414
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 14
44
VisualStudioVersion = 14.0.25123.0
55
MinimumVisualStudioVersion = 10.0.40219.1
6-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlobGZipUtility", "BlobGZipUtility.csproj", "{84285BB3-2556-45F3-965F-4667855A6EB6}"
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASGE", "ASGE.csproj", "{84285BB3-2556-45F3-965F-4667855A6EB6}"
77
EndProject
88
Global
99
GlobalSection(SolutionConfigurationPlatforms) = preSolution

BlobGZipUtility/Options.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
using CommandLine;
77
using CommandLine.Text;
88

9-
namespace BlobGZipUtility
9+
namespace ASGE
1010
{
1111
class Options
1212
{
1313
[Option('a', "account", Required = false, MutuallyExclusiveSet = "Account and Key",
14-
HelpText = "Storage account host. [sample.blob.core.windows.net]")]
14+
HelpText = "Storage account host. [mystorage]")]
1515
public string StorageAccount { get; set; }
1616

1717
[Option('k', "key", Required = false, MutuallyExclusiveSet = "Account and Key",
@@ -26,30 +26,41 @@ class Options
2626
HelpText = "Extensions to operate on. [.js, .css, .dat]")]
2727
public string[] Extensions { get; set; }
2828

29-
[Option('r', "replace", Required = false,
29+
[Option('r', "replace", Required = false, DefaultValue = false,
3030
HelpText = "Replace existing files in-place.")]
3131
public bool Replace { get; set; }
3232

33+
[Option('s', "simulate", Required = false, DefaultValue = false,
34+
HelpText = "Do everything except write to blob store.")]
35+
public bool Simulate { get; set; }
36+
3337
[Option('n', "newextension", Required = false,
3438
HelpText = "Copy file with a new postfix. [.gz]")]
3539
public string NewExtension { get; set; }
3640

37-
[Option('f', "container", Required = false,
41+
[Option('f', "container", Required = true,
3842
HelpText = "Container to search in.")]
3943
public string Container { get; set; }
4044

45+
[Option('x', "cacheage", Required = false, DefaultValue = 2592000,
46+
HelpText = "Duration for cache control max age header, in seconds. Default 2592000 (30 days).")]
47+
public int MaxAgeSeconds { get; set; }
48+
49+
4150
[HelpOption]
4251
public string GetUsage()
4352
{
4453
var help = new HelpText
4554
{
46-
Heading = new HeadingInfo("<<app title>>", "<<app version>>"),
47-
Copyright = new CopyrightInfo("<<app author>>", 2014),
55+
Heading = new HeadingInfo("Azure Storage GZip Encoder", "1.0"),
56+
Copyright = new CopyrightInfo("Stefan Gordon", 2016),
4857
AdditionalNewLineAfterOption = true,
4958
AddDashesToOption = true
5059
};
51-
help.AddPreOptionsLine("<<license details here.>>");
52-
help.AddPreOptionsLine("Usage: app -p Someone");
60+
help.AddPreOptionsLine("https://github.com/stefangordon/azure-storage-gzip-encoding\n");
61+
help.AddPreOptionsLine("\nExample 1: asge --extensions .css .js --container assets --replace --connectionstring <conn string>");
62+
help.AddPreOptionsLine("Example 2: asge --extensions .css .js --container assets --newextension .gz --account mystorage --key <storage key>");
63+
help.AddPreOptionsLine("\nUse either connection string (-c) or account and key (-a and -k).");
5364
help.AddOptions(this);
5465
return help;
5566
}

BlobGZipUtility/Program.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
using Microsoft.WindowsAzure.Storage.Auth;
1010
using Microsoft.WindowsAzure.Storage.Blob;
1111

12-
namespace BlobGZipUtility
12+
namespace ASGE
1313
{
1414
class Program
1515
{
@@ -18,6 +18,12 @@ static void Main(string[] args)
1818
var options = new Options();
1919
if (CommandLine.Parser.Default.ParseArguments(args, options))
2020
{
21+
if (string.IsNullOrEmpty(options.NewExtension) && !options.Replace)
22+
{
23+
Console.WriteLine("Must provide either -r (in-place replacement) or -n (new extension/postfix to append to compressed version).");
24+
return;
25+
}
26+
2127
CloudStorageAccount storageAccount;
2228

2329
if (!string.IsNullOrEmpty(options.ConnectionString))
@@ -37,17 +43,14 @@ static void Main(string[] args)
3743
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
3844
CloudBlobContainer blobContainer = blobClient.GetContainerReference(options.Container);
3945

40-
Utility.EnsureGzipFiles(blobContainer, options.Extensions, options.Replace, options.NewExtension, (int)TimeSpan.FromDays(30).TotalSeconds);
46+
Utility.EnsureGzipFiles(blobContainer, options.Extensions, options.Replace, options.NewExtension, options.MaxAgeSeconds, options.Simulate);
4147

4248
}
4349
else
4450
{
4551
// Display the default usage information
4652
//Console.WriteLine(options.GetUsage());
4753
}
48-
49-
Console.WriteLine("Press any key to exit.");
50-
Console.ReadKey();
5154
}
5255
}
5356
}

BlobGZipUtility/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
// General Information about an assembly is controlled through the following
66
// set of attributes. Change these attribute values to modify the information
77
// associated with an assembly.
8-
[assembly: AssemblyTitle("BlobGZipUtility")]
8+
[assembly: AssemblyTitle("ASGE")]
99
[assembly: AssemblyDescription("")]
1010
[assembly: AssemblyConfiguration("")]
1111
[assembly: AssemblyCompany("")]
12-
[assembly: AssemblyProduct("BlobGZipUtility")]
12+
[assembly: AssemblyProduct("ASGE")]
1313
[assembly: AssemblyCopyright("Copyright © 2016")]
1414
[assembly: AssemblyTrademark("")]
1515
[assembly: AssemblyCulture("")]

BlobGZipUtility/Utility.cs

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,30 @@
88
using System.Threading.Tasks;
99
using Microsoft.WindowsAzure.Storage.Blob;
1010

11-
namespace BlobGZipUtility
11+
namespace ASGE
1212
{
1313
class Utility
1414
{
1515

1616

17-
public static void EnsureGzipFiles(CloudBlobContainer container, IEnumerable<string> extensions, bool inPlace, string newExtension, int cacheControlMaxAgeSeconds)
17+
public static void EnsureGzipFiles(CloudBlobContainer container, IEnumerable<string> extensions, bool inPlace, string newExtension, int cacheControlMaxAgeSeconds, bool simulate)
1818
{
1919
Trace.TraceInformation("Enumerating files.");
2020

2121
string cacheControlHeader = "public, max-age=" + cacheControlMaxAgeSeconds.ToString();
2222

23-
var blobInfos = container.ListBlobs(null, true);
24-
//Parallel.ForEach(blobInfos, (blobInfo) =>
25-
foreach(var blobInfo in blobInfos)
23+
var blobInfos = container.ListBlobs(null, true, BlobListingDetails.Metadata);
24+
25+
Parallel.ForEach(blobInfos, (blobInfo) =>
2626
{
27-
CloudBlob gzipBlob = null;
28-
string blobUrl = blobInfo.Uri.ToString();
27+
CloudBlob gzipBlob = null;
2928
CloudBlob blob = (CloudBlob)blobInfo;
3029

3130
// Only work with desired extensions
3231
string extension = Path.GetExtension(blobInfo.Uri.LocalPath);
3332
if (!extensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
3433
{
35-
continue;
34+
return;
3635
}
3736

3837
// Check if it is already done
@@ -41,58 +40,68 @@ public static void EnsureGzipFiles(CloudBlobContainer container, IEnumerable<str
4140
if (string.Equals(blob.Properties.ContentEncoding, "gzip", StringComparison.OrdinalIgnoreCase))
4241
{
4342
Trace.TraceInformation("Skipping already compressed blob: " + blob.Name);
44-
continue;
43+
return;
4544
}
4645
}
4746
else
4847
{
49-
string gzipUrl = blobUrl + newExtension;
50-
gzipBlob = container.GetBlobReference(gzipUrl);
51-
48+
string gzipUrl = blob.Name + newExtension;
49+
gzipBlob = container.GetBlockBlobReference(gzipUrl);
50+
5251
if (gzipBlob.Exists())
5352
{
5453
Trace.TraceInformation("Skipping already compressed blob: " + blob.Name);
55-
continue;
54+
return;
5655
}
5756
}
5857

59-
// create a gzip version of the file
58+
// Compress blob contents
59+
Trace.TraceInformation("Downloading blob: " + blob.Name);
60+
61+
byte[] compressedBytes;
62+
6063
using (MemoryStream memoryStream = new MemoryStream())
6164
{
62-
// push the original blob into the gzip stream
6365
using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress))
6466
using (var blobStream = blob.OpenRead())
6567
{
6668
blobStream.CopyTo(gzipStream);
6769
}
70+
71+
compressedBytes = memoryStream.ToArray();
72+
}
6873

69-
// the gzipStream MUST be closed before its safe to read from the memory stream
70-
byte[] compressedBytes = memoryStream.ToArray();
71-
72-
// Blob to write to
73-
CloudBlockBlob destinationBlob;
74+
// Blob to write to
75+
CloudBlockBlob destinationBlob;
7476

75-
if (inPlace)
76-
{
77-
destinationBlob = (CloudBlockBlob)blob;
78-
}
79-
else
80-
{
81-
destinationBlob = (CloudBlockBlob)gzipBlob;
82-
}
77+
if (inPlace)
78+
{
79+
destinationBlob = (CloudBlockBlob)blob;
80+
}
81+
else
82+
{
83+
destinationBlob = (CloudBlockBlob)gzipBlob;
84+
}
8385

86+
if (simulate)
87+
{
88+
Trace.TraceInformation("NOT writing blob, due to simulation: " + blob.Name);
89+
}
90+
else
91+
{
92+
// Upload the compressed bytes to the new blob
8493
Trace.TraceInformation("Writing blob: " + blob.Name);
85-
86-
// upload the compressed bytes to the new blob
8794
destinationBlob.UploadFromByteArray(compressedBytes, 0, compressedBytes.Length);
88-
89-
// set the blob headers
95+
96+
// Set the blob headers
97+
Trace.TraceInformation("Configuring headers");
9098
destinationBlob.Properties.CacheControl = cacheControlHeader;
9199
destinationBlob.Properties.ContentType = blob.Properties.ContentType;
92100
destinationBlob.Properties.ContentEncoding = "gzip";
93101
destinationBlob.SetProperties();
94102
}
95-
}//);
103+
104+
});
96105
}
97106
}
98107
}

0 commit comments

Comments
 (0)