The only other way would be to actually produce 20 second mp3s from the start of all the songs, and put them in a different directory. And that way lies madness.
You may come up with a small PHP snippet, wich is accessed by a "download" button. The snippet reads the mp3 file as binary, but only a fixed amount of bytes from the beginning. This file-part would be sent to the requesting client using PHP's functions to send user generated HTTP headers.
The byte range for the cutting section should be great enough, since id3 tags may be stored at the beginning of the file (id3v2, the older id3v1 are located at the end of the file).
Of course, some players could have a problem with that, since the mp3 header fields are showing a different file length then the actual file size is. Media Player Classic (ie.) dislikes something like this, while winamp and VLC won't see any problems (and, if any, ignore them).
I didn't try this way out myself, but if won't take much to code something like that.
// edit by Chia
I'm on holidays, so I came up with this tiny code, wich can be tested on...
The code can be viewed on the same site...
The sample will be sent as a variable % of the filesize (ie. 25%) to compensate various bitrates resulting in various filesizes. Of course, if the song is 15 minutes, you'll get a relative large sample, but I think that won't be sooo bad. On the other end, if the original file is too small, the extracted sample won't contain enough data for the audio player to play the sample at all, so the script stops if filesize is below 1,5 MB (it also stops on various errors).