add

Showing posts with label website. Show all posts
Showing posts with label website. Show all posts

Thursday, November 17, 2011

Force a PDF to download

I recently needed to force a PDF to download using Apache. The default behaviour for most browsers is to try to open the PDF inside the browser itself. This is fine for a small PDF or for powerful machines - but a large PDF on even a modest machine can often lock the browser up. This needed fixing!

Little R&D of the Apache documents, you can get FilesMatch option which takes Regular Expressions. Initially I used something like this...
<files *.pdf=""></files><br />
<files *.pdf=""> ForceType application/pdf</files><br />
<files *.pdf=""> Header set Content-Disposition attachment</files><br />
This worked PERFECTLY - except some files had upper-case extensions and some had lower and I could see situations in the future where combinations of upper and lower case would be used too - just to piss me off! Because of this, not even this would work...

<filesmatch \.(pdf|pdf)=""></filesmatch>
<filesmatch \.(pdf|pdf)=""> ForceType application/pdf</filesmatch><filesmatch \.(pdf|pdf)=""> Header set Content-Disposition attachment</filesmatch>
That would match perfectly - as long as it was an EXACT match on upper OR lower case.
I was reaching the end of my patience - that is until I read the Using Character Classes on PerlDoc.
This showed me that I could force the RegEx (short for Regular Expressions) to match in a case-insensitive manner. This lead me to the following...
<filesmatch \.(?i:pdf)$=""></filesmatch>
<filesmatch \.(?i:pdf)$=""> ForceType application/pdf</filesmatch><filesmatch \.(?i:pdf)$=""> Header set Content-Disposition attachment</filesmatch>
However this only worked in proper browsers - and the bulk of the world are sadistic enough  to use Internet Explorer based ones. For some reason, if Internet Explorer see's the content type "Application/PDF" it will simply open it up in the reader. The solution? Why not pretend its a bog standard Octet Stream, just like a Zip file? After all, that's basically all it is; a binary file... A steam of bytes.
<FilesMatch "\.(?i:pdf)$">
ForceType application/octet-stream
Header set Content-Disposition attachment
FilesMatch>
And there you have it… A perfectly working modification to force all PDF files to download - this will work for any file extensions you chose to put into the FilesMatch argument!

Impotant Note :
You can put this code in either the htaccess or the vhost configuration for your server.
You can read more about FilesMatch at the Apache Document page.

Tuesday, September 13, 2011

extend flexigrid


It's quite easy to understand, what's the magic behind
flexigrid, so I am not a afraid of not beeing able to update, since my
flexigrid at least twice as powerfull as the original one... In Germany we
say "Kosten Nutzen Rechnung", dunno if the translation "Costs and Benefits
Calculation" will point it out...

But here's something for you!! You can extend any jquery plugin easyly by
using the correct extender-function.

look at the end of the flexigrid.js. here you will find several extentions,
the author already implemented. Just Copy-Paste one of them, change the name
und the method, that will be called... add private method to flexigrid..

Example:

$.fn.flexReload = function(p) { // function to reload grid

        return this.each( function() {
                if (this.grid&&this.p.url) this.grid.populate();
            });

    }; //end flexReload

This function should be in your flexigrid.js already.  Copy that and paste
it like this:

$.fn.flexMyExtendedFunc = function(p) { // function to reload grid

        return this.each( function() {
                if (this.grid&&this.p.url) this.grid.myprivatefunction();
            });

    }; //end flexReload

Now, search for the function "populate" ... you'll find something like this:

populate: function () { //get latest data
                if(p.loadingIndicatorFunc)
                    p.loadingIndicatorFunc(true);
                var g = this;

[....]

Again.. Copy paste the whole function and rename it to "myprivatefunction"
and, of course, change the code inside the function.

You can pass parameters as well!

And now you may ask, how to call this function??

very easy!

Let's says, you have a " <table id="myFlexTable"/>∓lt;/table&gt;



You did   "$("#myFlexTable").flexigrid(...); somewhere...

Now just call  $("#myFlexTable").flexMyExtendedFunc();" 
and the code INSIDE the flexigrid ("myprivatefunction") will be executed. You have full control
in here... you can access all variables, the flexigrid uses...

And what about updating?

If you really JUST add a new extension method AND ONLY add methods to the
flexgrid-plugin, you can easyly copy-paste them to a new version.... That's
how I would do it... Anyway, trust me, if you ll get to understand the code,
the other way - adding updates via copy-paste to your version of flexigrid,
might be a lot faster...

Hope that helps some people out there, who try to expand the flexigrid.

Source code http://flexigrid.info/

Thursday, October 22, 2009