tags:

views:

387

answers:

3

Hi there

I'm using this approach to display an icon near each link to a file from my web-application.

In order to avoid IE history cache problems I display a link as

<a href="path/to/the/file.xls?timestamp=0234562">FileName.xls</a>.
In this case the css rule doesn't do his job.

Do you know how can I solve this problem?

+4  A: 

The selector a[href$='.xls'] you probably use, applies only if it matches the end of HREF's value. Use a[href*=.xls] instead.

Excerpt from Selectors Level 3:

[att*=val]

Represents an element with the att attribute whose value contains at least one instance of the substring "val". If "val" is the empty string then the selector does not represent anything.

Edit

If you have control over the .htaccess file, you may ensure there to avoid cache problems, so you can use your original stylesheet rules. See Cache-Control Headers using Apache and .htaccess for further details.

Török Gábor
But that'd match "file.xls.zip" as well, and I don't think their icons would be the same...
Seb
@Seb In that case you can write `href*=.xls?`.
Török Gábor
@Torok: no, because that would match any string _containing_ ".xls", as the example I gave.
Seb
@Seb: I can't see why. The quotation mark in the end does not allow other patterns. And you can still write `href*=.xls?timestamp=`.
Török Gábor
+1  A: 

The problem is that a[href$='.xls'] matches the end of the href attribute of your anchor, but you're appending the timestamp, so the ending of that href is actually the timestamp.

To avoid caching problems you could handle the downloads using a proxy; that is, use a script that triggers the download of files. In PHP it's easily accomplised with readfile() function and sending no-cache headers, for example:

<a href="download.php?file=spreadsheet.xls">spreadsheet.xls</a>

But since I don't know which programming language you're using, I couldn't say much more.

Seb
i'm using php. can you explain ur approach?
Duncan Benoit
A: 

Duncan, I know this has already been answered, but just for your comment, here is a function that should work for you. I think it is almost straight off the PHP manual or some other example(s) somewhere. I have this in a class that handles other things like checking file permissions, uploads, etc. Modify to your needs.

public function downloadFile($filename)
{

    // $this->dir is obviously the place where you've got your files
    $filepath = $this->dir . '/' . $filename;
    // make sure file exists
    if(!is_file($filepath))
    {
        header('HTTP/1.0 404 Not Found');
        return 0;
    }
    $fsize=filesize($filepath);

    //set mime-type
    $mimetype = '';
    // mime type is not set, get from server settings
    if (function_exists('finfo_file'))
    {
        $finfo = finfo_open(FILEINFO_MIME); // return mime type
        $mimetype = finfo_file($finfo, $filepath);
        finfo_close($finfo);
    }
    if ($mimetype == '')
    {
        $mimetype = "application/force-download";
    }

    // replace some characters so the downloaded filename is cool
    $fname = preg_replace('/\//', '', $filename);
    // set headers
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Type: $mimetype");
    header("Content-Disposition: attachment; filename=\"$fname\"");
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: " . $fsize);

    // download
    $file = @fopen($filepath,"rb");
    if ($file)
    {
        while(!feof($file))
        {
            print(fread($file, 1024*8));
            flush();
            if (connection_status()!=0)
            {
                @fclose($file);
                die(); // not so sure if this best... :P
            }
        }
        @fclose($file);
    }
}
sims