Friday 29 February 2008

The western front...

All is quiete around here and has been for a while.

This is mainly due to me having to learn ActionScript (again) to pull a project out of the gutter so I will be spending most of the weekend (and any other *spare* time I might have) living and breathing AS2 classes and wishing I was a lot better versed in the drawing API and the old EventDispatcher. Although I'm not doing bad having not done any serious ActionScript in the last 18 is months.

The project is top secret so I can't say much more but maybe I'll have some lovely little learnings to write about if and when I get the time.

Tuesday 26 February 2008

Shrinking Log files in SQL Server 2005

So you, like I, have a database in SQL Server 2005 who's log file (.ldf) has grown massive.

Here is a quick but of SQL that should help you shrink the file to reclaim some disk space. be warned, this might impeed your ability to restore the database later if it all goes wibble.

First run the following


USE nameOfTheDatabaseHere
SELECT * FROM sysfiles



Now, take note of the fileid of the log file (usualy 2 for most databases) then do

DBCC SHRINKFILE
( fileIDGoesHere, TRUNCATEONLY )



This will truncate the log file to as small as the DB Server will allow.

See http://msdn2.microsoft.com/en-us/library/aa258824.aspx for more info

Thursday 21 February 2008

WOW

This is ace.

It's like all that microsoft *seadragon* or what ever it was called

http://www.cooliris.com/

Wednesday 20 February 2008

Downloading and Deleting Temporary Files

Recently while working on some functionality for one of our clients I found myself in a position where I needed to add some images to a zip file. This zip file then needed to be sent to the end user as a download (Content-disposition: attachment;).

Once the user had downloaded the file, the zip file needed to be deleted so as not to leave temp files on the servers disk.

I tried a few things like calling File.Delete("path/to/file.zip") after doing Response.TransferFile() or Response.WriteFile() but I found that the page never loaded. I guess it was deleting the file bfore it had chance to stream the file to the client.

Eventually I came up with the code below which reads the entire file into a BinaryWriter and the write it out to the Response's OutputStream. The stream is then flushed and the file can be deleted.
    string theFile = "path/to/your.file";
FileInfo theFileInfo = new FileInfo(theFile);

if(theFileInfo.Exists) {
// Clear any output
Response.Clear();
Response.BufferOutput = true;
// should be the MIME-Type of your file
Response.ContentType = "application/x-zip-compressed";
// set the name of the file as it will be downloaded
Response.AddHeader("Content-Disposition", "attachment; filename=the.file");

// Open the OutputStream into a BinaryWriter
BinaryWriter br = new BinaryWriter(Response.OutputStream);
// Read the entire temporary file and write it into the BinaryWriter
br.Write(File.ReadAllBytes(theFileInfo.FullName));
// Flush and Close the Writer
br.Flush();
br.Close();

// Fulsh the Response object
Response.Flush();

// Delete the temporary file
File.Delete(theFileInfo.FullName);
// End the execution of the page
Response.End();
}

While this does get the job done it isn't perfect. The entire file is read into memory before being sent to the client. This means if you are sending large files to many clients at the same time you could have some trouble with the server running out of memory and all manner of other crazy things happening (possibly).

As ever, use at your own risk.

Monday 18 February 2008

IPod what!


I'm sat on to virgin cross country service from Leeds to Sheffield and there is a girl sat next to me seemingly using an old laptop kitted out with iTunes to do nothing else but listen to music. I on the other hand am listening to music on my IPod, while blogging from my phone. Technology ay?!

Friday 15 February 2008

More...

More mindless drivel and ramblings now available free over at twentysix Opinions.

Wednesday 13 February 2008

SQL Noise

Someone's going to be annoyed when they end up here looking for how to add "noise" to an SQL query.. oh well, sorry...

However, it is an appropriate title because after adapting Matt's SQL on FIRE, I truly feel I'm bringing the noise (to SQL [in my own little way])!

Today really is SQL Day 2008 (another dead end search result there! :)

SQL : Multiple Order By's

Just trying to sort a query with an ORDER BY clause where I needed to order by two columns in different directions so I tried it and it works! Didn't know you could do that...
SELECT * FROM tblTableName
WHERE column1='x'
AND column2='y'
ORDER BY column3 ASC, column4 DESC
Nice!

(tested in MySQL and MS SQL)

Monday 11 February 2008

Banana Cake v0.011111 alpha beta gama delta something or other LIVE!

Today I put the first version of Banana Cake live on an internal web server and invited my co-developers here at twentysix leeds to become my testers.

We've got a couple of current projects set up on there and I hope the guys will use it to track what they are doing and hopefully provide me with some excellent and useful feedback over the next few weeks.

If they do and and they find it useful day to day then my plan is to roll it out to the entire office ( a whole 25 users !) . With a bit of luck I'll have come up with a real name for it by then and sorted out the dicey interface although gay Dave says he likes the way it looks as it is...

I'm off to look at the bugs list for Banana Cake and get some issues sorted.

Wednesday 6 February 2008

Blog code formatting tool

While I was writing that last post I went hunting for a code formatting tool for my code inserts and came across Format MY Source Code for Blogging.

It's not quite what I wanted but I'm not about to write a C# syntax highlighter so it'll do for now

Tuesday 5 February 2008

ASP.net Image Upload and Resize (in C# .net 2.0, 3.0, 3.5, visual studio 2005, visual studio 2008)

Please excuse the ridiculously long title but I kinda want to make search engines love this post because I keep having to google for it.

What follows is what I have found to be the simplest and most elegant method of uploading, resizing and saving an image in ASP.NET. So let's get to it.

Ok, lets assume we have a FileUpload control (named fuImageFile) and a Button control (btnUpload) and we're going to upload the image when we click our button. The simplest method of uploading our file might look something like this

protected string savePath = "~/uploaded/";

protected void btnUpload_Click (object sender, EventArgs e) {
string fileName = fuImageFile.FileName;
string saveName = Server.MapPath(savePath) + fileName;
fuImage.SaveAs(saveName);
}


So now we can upload an image to our server, what about resizing that image? For this to work you will need to add a using directive for System.Drawing and System.Drawing.Imaging

using System.Drawing;
using System.Drawing.Imaging;

Next we'll look at how we go about resizing an image (in the form of a Bitmap object) and then at how to integrate that into our upload page.

public Bitmap ResizeBitmap (Bitmap src, int newWidth, int newHeight) {
Bitmap result = new Bitmap(newWidth, newHeight);
using ( Graphics g = Graphics.FromImage((System.Drawing.Image)result) ) {
g.DrawImage(src, 0, 0, newWidth, newHeight);
}
return result;
}


This method takes a Bitmap object and two numbers specifying the height and width of the required image. We then create a new empty Bitmap at the desired size (result) , we then obtain a Graphics object from it (NB: the Graphics object remains associated with the Bitmap) and draw our source image into it.

When we return the result we have an Bitmap object with the image data we drew into the Graphics object.

So now lets work it into our page

protected void btnUpload_Click (object sender, EventArgs e) {
string fileName = fuImageFile.FileName;

// Get the bitmap data from the uploaded file
Bitmap src = Bitmap.FromStream(fuImageFile.PostedFile.InputStream) as Bitmap;

// Resize the bitmap data
Bitmap result = ResizeBitmap (src, 200, 200);

string saveName = Server.MapPath(savePath) + fileName;
result.Save(saveName, ImageFormat.Jpeg);
}
What we do here is take the InputStream of the FileUpload's PostedFile property and create a Bitmap with it, once we have this bitmap object we can call it's Save method to save it to the local disk.

Proportional Resizing

The problem with this ResizeBitmap is that it will stretch and pull your input image to fit the dimensions supplied which 99% of the time is not what we will want. We usually want to scale an image keeping its proportions. Take a look at the ProportionallyResizeBitmap method below:


public Bitmap ProportionallyResizeBitmap (Bitmap src, int maxWidth, int maxHeight) {
// original dimensions
int w = src.Width;
int h = src.Height;

// Longest and shortest dimension
int longestDimension = (w>h)?w: h;
int shortestDimension = (w<h)?w: h;

// propotionality
float factor = ((float)longestDimension) / shortestDimension;

// default width is greater than height
double newWidth = maxWidth;
double newHeight = maxWidth/factor;

// if height greater than width recalculate
if ( w < h ) {
newWidth = maxHeight / factor;
newHeight = maxHeight;
}

// Create new Bitmap at new dimensions
Bitmap result = new Bitmap((int)newWidth, (int)newHeight);
using ( Graphics g = Graphics.FromImage((System.Drawing.Image)result) )
g.DrawImage(src, 0, 0, (int)newWidth, (int)newHeight);
return result;
}

This method takes a maxWidth and a maxHeight instead of a newWidth and newHeight, it then does a bit of maths to figure out which is the longest, the original height or the original width, works out the ratio of these two numbers and applies them appropriatley to the target size and resizes the image accordingly.

Just like ResizeBitmap, ProportionallyResizeBitmap returns a Bitmap object so you can simply substitute the call to ResizeBitmap in the button click method and it will all play nicely!

Gotchas

If you get a "Generic Error from GDI +" like Exception Details: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+ then you should check the following points:
  • Make sure the destination folder exists
  • Make sure the the local machine user ISS_WPG has write permissions to the destination folder
  • Make sure the save path is correctly escaped
[more to follow maybe]

See the Microsoft Knowlage Base article http://support.microsoft.com/?id=814675 for more posibilities

Done it again

So I did it again... I was close to getting inyerface ready for it's next/first launch and then I started faffing with Banana Cake which is getting near a point where I feel I might let the gang on the development team at work be my alpha testers although I've realised there are a few more little features need adding before it is actually useful.

Then, I've decided, for the inyerface image management module, instead of learning ActionScript 3 I'm going to cobble it out in AS1/2 just to get it up and running then maybe one day I'll re-make it in ASWhatever.