
Introduction
This article describes how, using the DiscUtils library from CodePlex, you can serve up customized ISO files from a website.
Background
I've been working on the DiscUtils library for a couple of months, and I thought it would be a good idea to show how it can be used in practice. CodeProject seemed like the ideal place to expose some of the capabilities of the DiscUtils library.
DiscUtils itself provides an Open Source library for creating, reading, and modifying various disk image formats, including .ISOs. The DiscUtils library is implemented in pure C# (no P/Invoke or COM Interop), and doesn't load the entire disk image into memory, so has a relatively small memory footprint. This makes it perfect for use in websites. This article describes one such use of the library, to create .ISO images on request using ASP.NET. Specifically, the code injects a mock license file into the ISOs - but any kind of image customization is possible.
Using the Code
The code is a very simple ASP.NET website, created in Visual Web Developer 2008 Express Edition. I've re-arranged the project files slightly, so they exist in a single directory hierarchy.
The interesting code is in CreateISO.ashx. There is a using
statement to pull in the DiscUtils.Iso9660
namespace (the DLL itself is placed in the Bin folder of the solution). The ProcessRequest
method creates the ISO file; first, the CD Builder is initialized:
CDBuilder builder = new CDBuilder();
builder.UseJoliet = true;
builder.VolumeIdentifier = "GENERATED_CD";
Enabling Joliet is recommended (permits long file names), and the Volume Identifier can be set to any string (subject to constraints of the ISO 9660 specification).
Next, the contents of the CD need to be specified. In this case, we include all files from the ~/App_Data/CDRoot folder:
DirectoryInfo di = new DirectoryInfo(context.Server.MapPath("~/App_Data/CDRoot"));
PopulateFromFolder(builder, di, di.FullName);
The PopulateFromFolder
method is defined later in the file - it simply recurses through the directory structure, adding any files found to the ISO image:
public static void PopulateFromFolder(CDBuilder builder,
DirectoryInfo di, string basePath)
{
foreach (FileInfo file in di.GetFiles())
{
builder.AddFile(file.FullName.Substring(basePath.Length), file.FullName);
}
foreach (DirectoryInfo dir in di.GetDirectories())
{
PopulateFromFolder(builder, dir, basePath);
}
}
After populating the ISO image with all of the 'normal' files from the disk, it's time to customize the image. Here, we're simply creating a new file 'LICENSE.LIC' that contains some dummy licensing information. You could customize the ISO image in any way you choose.
MemoryStream ms = new MemoryStream();
StreamWriter writer = new StreamWriter(ms, Encoding.ASCII);
writer.WriteLine("LICENSE FILE");
writer.WriteLine("Issued By: Acme, Inc.");
writer.WriteLine("Issued On: " + DateTime.UtcNow);
writer.Flush();
builder.AddFile("LICENSE.LIC", ms.GetBuffer());
Next, the HTTP headers are set. Since there is no registered Internet Media Type for ISO images, application/octet-stream is used. The Content-Disposition header instructs Internet Explorer to offer a 'Save As...' dialog box, and also provides the default file name for the ISO file.
context.Response.ClearContent();
context.Response.ClearHeaders();
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Disposition",
"attachment; filename=newiso.iso");
Finally, the ISO image is finalized using Build()
, and we simply pump the data from the resulting stream to the HTTP response stream.
Stream cdStream = builder.Build();
byte[] buffer = new byte[64 * 1024];
int numBytes = cdStream.Read(buffer, 0, buffer.Length);
while (numBytes != 0)
{
context.Response.OutputStream.Write(buffer, 0, numBytes);
numBytes = cdStream.Read(buffer, 0, buffer.Length);
}
Points of Interest
This article illustrates that you can create ISO images using the DiscUtils library either from existing files, or by providing a byte array. You can also supply a Stream
instance.
The DiscUtils library doesn't currently support El Torito format, so it isn't suitable for projects where you need to provide a bootable CD.
If you find any bugs or problems with the code in this article, please post comments below. If the problem is with the DiscUtils library, please post an Issue on the CodePlex project.
History
None (yet).