ExtJS grid form with document in MySQL - php

I have a grid whith the data that come from a database. Each row of the grid containt these fields : document name, owner, version etc. The content of the document is in a blob.
I want, when the user double-click on a row, to download the content of the document. The best way will be a pop-up that ask a confirmation. The grid must stay on the screen.
I'm able to read the content of the document with an ajax request and put the result in a variable.
Ext.Ajax.request({
url: '../controleurs/c_get_doc_content.php',
method: 'POST',
params: { dep: r.data.nom_document },
success: function(response, opts) {console.log(response);console.log(opts)},
requestcomplete: function (conn, response, options) {},
failure: function() {console.log('failure');},
headers: { 'my-header': 'foo' },
How can I save the content of the document to a file on the user PC ?

The best solution for this is server side. Instead of passing the blob to the JS, you just pass an ID. Then when the user chooses to download the file, you call the server and it returns a document that can be downloaded.
You would just stream that content as an attachment instead of sending it with the AJAX request
in PHP you use the following code to make sure a file is downloaded and the save as dialog is displayed.
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}

Set the content type of your PHP response to something the browser would want to save....

Related

PHP download freezes everything else

I'm running the following code to download a file in the backround instead of just redirecting to the file in the browser, but I can't click on anything else on the page until the whole file is downloaded. Anything I can change in the code to fix that?
When clicking on a link this is loaded in a separate php file, so the user doesn't see where the file is fetched from ($filepath) and it's also protected by a session:
header("Cache-control: private");
header("Content-Type: application/octet-stream");
if ($download) {
header("Content-Disposition: attachment; filename=\"" . $title . "\"");
header('Content-Transfer-Encoding: binary');
} else {
header("Content-Disposition: inline; filename=\"" . $title . "\"");
}
// Disable caching
header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
header('Pragma: no-cache'); // HTTP 1.0.
header('Expires: 0'); // Proxies.
readfile($filepath);
Edit // I still haven't been able to figure this out. Now I'm trying with this AJAX code but it still locks the whole page until the file is fully downloaded and it only loads in the background, not to the harddrive.
$('.download').on('click', function(e) {
e.preventDefault();
var self = $(this);
$.ajax({ type: 'POST',
url: self.attr('href'),
async: true,
success : function(response)
{
}
})
});
Disclaimer: all below is valid for the default file-based sessions. For other handlers it may not stay true.
It's sessions that block: as soon as one page has the session open no other page for the same session id would be served.
The solution would be to close the session as soon as you're done with it.
So put
session_write_close();
right before you started serving your file.
It would close the session for the page that serves that file and other pages can be served after that, even though the file is not downloaded fully yet.
References:
http://php.net/manual/en/function.session-write-close.php

How to trigger a download prompt through post callback function

simple question I guess, but can't figure it out... Here's the problem:
In the front end, I export some user-selected data to the server to dynamically create a file:
$("#export-button").click(function() {
$.post("'.$postUrl.'",{variable:exportSelection},
function(data) {
console.log(data);
}
);});
Then, after I receive the data and create/save the file on the server, I am doing the following in php:
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;}
What am I supposed to do in the post callback function instead of printing on the console in order to get a download prompt?
UPDATE: OK - I just realised that my #export-button was an anchor tag with no href... Now when I point to the file on the server, the problem is that when I click, it follows the link prompts to save file etc., but it gets to the file BEFORE the "new" version is generated (so using the previous selection at each click)
OK - I figured it out. I just needed to disable the link from pointing anywhere and then do:
window.location = 'my_file_location.doc';
... inside the callback function

PHP download/redirect

Okay so this is how I rewrote it. Any changes? Will this work? I've added the Javascript at the end with the timeout.
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
}
?>
<script type="text/Javascript">
window.setInterval(function()
{
window.location = "www.moneymovers.com";
}, 5000);
</script>:
You can't download and then do a header redirect. The client is going to redirect as soon as it sees the header, which means the download won't work. But you also can't output the header after the download, because then the redirect won't happen. Either way, it's not gonna work.
I would recommend doing this at a different level. For example, when the user clicks the download link, have some JavaScript start the download in a new tab/window and then redirect to the desired location in the current tab.
You can put the location header wherever you want, as long as nothing has been outputted (echo).
If you have outputted something, you can output something like this to redirect :
<script type="text/javascript">
window.location = "www.example.com";
</script>
EDIT :
In your case, it is not possible to do what you're looking for, as far as I know. You will have to manage this case in the caller page. The Javascript will not be called because you've modified the Content-Disposition.

Second sequential function stomps the first function

I guess I have to break down and ask for help. (Should have done it 3 days ago!)
Here's what happens...
PHP reads session & post variables, builds a .csv file from a mysql query.
it attempts to open a 'Save As' dialog box and when that's done, jump to another page.
I'm using nested functions but when run, the dialog box seems to get run over and never appears.
separately the functions work fine.
when run, the 'save as' dialog box doesn't wait for user input
Can anyone see what I've done wrong or can you redirect my thinking?
$filename points to the created CSV file on the server
$suggname is a default filename users should see in the dialog box.
The code:
holdit($filename,$suggname);
function holdit($filename,$suggname) {
$fp=#fopen($filename, 'rb');
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) {
header('Content-Type: "application/octet-stream"');
header('Content-Disposition: attachment; filename="'.$suggname.'"' );
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".filesize($filename));
} else {
header('Content-Type: "application/octet-stream"');
header('Content-Disposition: attachment; filename="'.$suggname.'"' );
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".filesize($filename));
}
fpassthru($fp);
fclose($fp);
jump();
}
function jump() {
header('Location: return_from_csv.php');
}
You are adding lots of headers to your HTTP response. One of those is Location which instructs the browser to redirect. Obviously it is interpreting that as a higher priority than your other headers.
Decide if you want to redirect or serve a file in your response and do one or the other.
I suspect you have misunderstood the Location header. Read this: http://en.wikipedia.org/wiki/HTTP_location
By the looks of things you are trying to serve the CSV file and then redirect to another page. Sorry, you cannot do this. An HTTP response does one thing and one thing only. You might consider opening your link to the CSV file in another window using the target attribute of <a>.

How can I allow users to download pictures (.gif,.png,.jpeg)?

How can I allow users to download pictures saved on the server? The goal is to have the user click on a link and have a specified image to start to download.
Facebook example:
Make the link to another .php page, not the image. Then on that page use the content-disposition header like this:
<?php
// Define the name of image after downloaded
header('Content-Disposition: attachment; filename="file.jpg"');
// Read the original image file
readfile('file.jpg');
?>
From there, you can just add the filename of the image in a get command like
`download.php?filename=file`
then reference that in the file as:
readfile($_GET['filename'].'.jpg')
You need to set a specific header on the response that delivers the image in order to force a download.
Content-Disposition: attachment; filename=myawesomefilename.png
Otherwise it will just load up in browser.
So send that header and then just link to the path that delivers that image with that header.
Send a header to tell the browser to download it like this:
header("Content-type: application/force-download")
Then send them the data for the file itself without any HTML or anything.
This example is snipped from the PHP docs
<?php
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
If by "download pictures saved on the server" you mean "try to make the browser offer a 'save as' dialog box instead of just displaying the image" then you might want to look into using the Content-Disposition: attachment header in the response that serves the image:
Content-Disposition: attachment; filename="thefilename.jpg"
You can set headers in php using the header function.

Categories