Soma Posted September 25, 2013 Share Posted September 25, 2013 A quick tutorial how to create file downloads using pages You will be able to create a new page using template "PDF" (or any you setup), upload a pdf file. You then can select this page using page fields, or links in Wysiwyg. The url will be to the page and NOT the file itself. This will allow to keep a readable permanent unique url (as you define it), unlike /site/assets/files/1239/download-1.pdf, and you'll be able to update/replace the uploaded file without worring about its filename. Further more the file will also have an id, the one of the page where it lives. Clicking those links will download or open the file (when target="_blank") like it would be a real file on server with a path like /downloads/project/yourfile.pdf. You'll be also able to use the "view" action directly in the page list tree to view the file. Further more you'll be able to esaily track downloads simply by adding a counter integer field to the template and increase it every time the page is viewed. Since the file is basicly a page. This all works very well and requires only minimal setup, no modules and best of it it works in the same way for multi-language fields: Just create the language alternative fields like "pdf, pdf_de, pdf_es" and it will work without modifying any code! Still with me? ok PW setup Download folder: Create a template "folder" or "download-folder" with only a title needed. Create pages in the root like /downloads/project/ using this template. Setup the template for the pdf files 1. Create a new template in PW. Name it pdf 2. Goto template -> URLs tab and set the URL end with slash to no. (So we can have /path/myfile.pdf as the URL) 3. Create a new custom file field, name it pdf. Set its maximal count to 1 under -> Details tab. 4. Add the pdf field created to the pdf template. Easy. 5. Create a new "pdf" page using the pdf template under a download folder you created earlier. 6. Give it the title and in the name field add ".pdf" to the end (could also leave as is) Template PHP file for the pdf files 1. Create the template file pdf.php in your /site/templates folder 2. add the following code: <?php // pdf.php if($page->pdf){ wireSendFile($page->pdf->filename); } Done. To see the options you have with PW's wireSendFile() you can also overwrite defaults <?php // pdf.php if($page->pdf){ $options = array( // boolean: halt program execution after file send 'exit' => true, // boolean|null: whether file should force download (null=let content-type header decide) 'forceDownload' => false, // string: filename you want the download to show on the user's computer, or blank to use existing. 'downloadFilename' => '', ); wireSendFile($page->pdf->filename, $options); } Simple and powerful isn't it? Try it out. Some thoughts advanced Create as many file types as you like. It might also be possible to use one "filedownload" template that isn't restricted to one field type but evaluate it when being output using $page->file->ext, or save the file extension to the page name after uploading using a hook. One last thing. You can add other meta fields or preview images to the template and use those to create lists or detail pages. It's all open to goodness. Again all without "coding" and third-party modules. Further more you can use the excellent TemplateDecorator to add icons per template and have a nice pdf icon for those pages. This as a base one could also easily create a simple admin page for mass uploading files in a simple manner, and create the pages for the files automaticly. ImagesManager work in the same way. Cheers 35 2 Link to comment Share on other sites More sharing options...
kongondo Posted September 25, 2013 Share Posted September 25, 2013 Thanks for this Soma! Very elegant solution 3. Create a new custom field, name it pdf. Set it's maximal count to 1. What type of field please? 1 Link to comment Share on other sites More sharing options...
Soma Posted September 25, 2013 Author Share Posted September 25, 2013 Thanks, I corrected and rewrote part of it. 1 Link to comment Share on other sites More sharing options...
cstevensjr Posted September 26, 2013 Share Posted September 26, 2013 Applause! 1 Link to comment Share on other sites More sharing options...
einsteinsboi Posted September 30, 2013 Share Posted September 30, 2013 Nice! Thank you Soma 1 Link to comment Share on other sites More sharing options...
fmgujju Posted September 30, 2013 Share Posted September 30, 2013 Thank you Soma! I needed one for my current website development and I got it working nicely with your quick tutorial on http://mssoonline.org project. Thanks again. 1 Link to comment Share on other sites More sharing options...
thetuningspoon Posted October 11, 2013 Share Posted October 11, 2013 I hadn't really thought about the advantages that could be derived from doing it this way. This could definitely work well for some sites. Maybe "ImagesManager" could be expanded to "FileManager"? Thanks for the tutorial! Link to comment Share on other sites More sharing options...
Macrura Posted October 12, 2013 Share Posted October 12, 2013 thanks soma, just used this on a project, really solved a need. Link to comment Share on other sites More sharing options...
fisnik Posted November 20, 2013 Share Posted November 20, 2013 This is working fine, only when i use language alternative fields it is not showing the other language file. i have created both fileds pdf and pdf_de. This is the code that i am currently using to call the files: <?php $features = $pages->get("1029")->children("limit=6, sort=sort"); foreach($features as $feature) { echo "<li>" . "<a class='readmore4' href='{$feature->url}'><p class='texti4'>{$feature->title}</p></a>" . "</li>"; } ?> Link to comment Share on other sites More sharing options...
Soma Posted November 20, 2013 Author Share Posted November 20, 2013 I'm not sure why it's not working for you without seeing the whole. Make sure you have trailing slash disabled for the template and language are active etc. Link to comment Share on other sites More sharing options...
joe_ma Posted March 31, 2014 Share Posted March 31, 2014 I have tried to implement this on a multilanguage site and also got only the one pdf from the main language. Here's what I did: - created a fieldtype "file" for every language (pdf, pdf_fr, pdf_it) - created a template "pdf" with all these fields - created "pdf.php" with the above code - uploaded corresponding pdf-files into these fields - in the body text I linked to the pdf-files (which worked as expected: in all languages I could link to the corresponding files) What happens is, that in all languages you get always the pdf-file from the main language. So I tried to modify the code for the pdf.php like this: if ($page->pdf) { wireSendFile($page->pdf->filename); } elseif ($page->pdf_fr) { wireSendFile($page->pdf_fr->filename); } else { wireSendFile($page->pdf_it->filename); } Still only the one version from the main language. So I tried this: if ($user->language == "default") { if ($page->pdf) { wireSendFile($page->pdf->filename); } } elseif ($user->language == "francais") { if ($page->pdf_fr) { wireSendFile($page->pdf_fr->filename); } } else { if ($page->pdf_it) { wireSendFile($page->pdf_it->filename); } } That produces a blank page when clicking on the link to the file. I don't seem to be capable to get it right. Link to comment Share on other sites More sharing options...
Soma Posted March 31, 2014 Author Share Posted March 31, 2014 What version of PW are you using? Cause there was a problem with alternative language file fields that was fixed not so long ago. Link to comment Share on other sites More sharing options...
Wanze Posted March 31, 2014 Share Posted March 31, 2014 if ($user->language == "default") { Your if statements won't work because $user->language is a Language object. So you could try: if ($user->language->name == 'default') // Or if your values are titles rather than names if ($user->language->title == 'francais') 3 Link to comment Share on other sites More sharing options...
joe_ma Posted April 1, 2014 Share Posted April 1, 2014 What version of PW are you using? 2.4.0. Link to comment Share on other sites More sharing options...
joe_ma Posted April 1, 2014 Share Posted April 1, 2014 Thanks, Wanze. I have tried your version. And lo! it works! Link to comment Share on other sites More sharing options...
Soma Posted April 1, 2014 Author Share Posted April 1, 2014 The alternative lang fields work fine, so your doing something wrong. Are the langs really named fr it? Are the file field limited to 1 file upload? Link to comment Share on other sites More sharing options...
jean-luc Posted November 5, 2014 Share Posted November 5, 2014 Using wireSendFile() for flexible download is great to mask the real file location on the server or to select the file according to the language, but it comes with an issue that appears for large files or slow connections: until the download completes, any other access to the website from the same session is blocked. For a user viewing a page that contains such a download link, this means that when he clicks on the download link, the download starts as expected, but until the download completes, the user can not navigate to a different page of the site, which is probably not the expected behavior. The solution to avoid this issue is to call session_write_close() before wireSendFile(), like this: $options = array( // boolean: halt program execution after file send 'exit' => true, // boolean|null: whether file should force download (null=let content-type header decide) 'forceDownload' => true, // string: filename you want the download to show on the user's computer, or blank to use existing. 'downloadFilename' => $clientFilename, ); // Close the php session, so wireSendFile doesn't block other connections from the same session while downloading session_write_close(); wireSendFile($serverFilePath, $options); This should not have any unwanted effect as long as the 'exit' option is set to true (because wireSendFile() calls exit() just after readfile() in this case). Note: The issue comes from PHP's session management, where "session data is locked to prevent concurrent writes only one script may operate on a session at any time" (as says PHP session_write_close documentation ). A google search "php readfile session_write_close" brings many exemple of this lock problem. 3 Link to comment Share on other sites More sharing options...
Soma Posted November 5, 2014 Author Share Posted November 5, 2014 Interesting. But then you're logged out? Link to comment Share on other sites More sharing options...
jean-luc Posted November 5, 2014 Share Posted November 5, 2014 Interesting. But then you're logged out? No, you stay logged in. Actually, session_write_close() does not close the current session, but only "End the current session and store session data." (see http://fr2.php.net/manual/en/function.session-write-close.php) Link to comment Share on other sites More sharing options...
bora Posted October 8, 2015 Share Posted October 8, 2015 Hello, When I try this, it downloads the files (in my test case a docx file). It works but two things happen. 1- It renames file to download.doc 2- It converts the extension from docx to doc Any idea why that happens? Hello, When I try this, it downloads the files (in my test case a docx file). It works but two things happen. 1- It renames file to download.doc 2- It converts the extension from docx to doc Any idea why that happens? Ok just after a second later figured it out. Setting forceDownload to false causes both of them. Works perfectly fine now, many thanks Soma. Link to comment Share on other sites More sharing options...
Batyr Posted January 12, 2018 Share Posted January 12, 2018 Thank you @Soma you made my day! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now