I am trying to download files using Ajax and show a custom download progress bar.
The problem is I can't understand how to do so. I wrote the code to log the progress but don't know how to initiate the download.
NOTE: The files are of different types.
Thanks in advance.
JS
// Downloading of files
filelist.on('click', '.download_link', function(e){
e.preventDefault();
var id = $(this).data('id');
$(this).parent().addClass("download_start");
$.ajax({
xhr: function () {
var xhr = new window.XMLHttpRequest();
// Handle Download Progress
xhr.addEventListener("progress", function (evt) {
if(evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
}
}, false);
return xhr;
},
complete: function () {
console.log("Request finished");
}
})
});
HTML and PHP
<li>
<div class="f_icon"><img src="' . $ico_path . '"></div>
<div class="left_wing">
<div class="progressbar"></div>
<a class="download_link" href="#" id="'.$file_id.'"><div class="f_name">' . $full_file_name . '</div></a>
<div class="f_time_size">' . date("M d, Y", $file_upload_time) . ' ' . human_filesize($file_size) . '</div>
</div>
<div class="right_wing">
<div class="f_delete">
<a class="btn btn-danger" href="#" aria-label="Delete" data-id="'.$file_id.'" data-filename="'.$full_file_name.'"><i class="fa fa-trash-o fa-lg" aria-hidden="true" title="Delete this?"></i>
</a>
</div>
</div>
</li>
If you want to show the user a progress-bar of the downloading process - you must do the download within the xmlhttprequest. One of the problems here is that if your files are big - they will be saved in the memory of the browser before the browser will write them to the disk (when using the regular download files are being saved directly to the disk, which saves a lot of memory on big files).
Another important thing to note - in order for the lengthComputable to be true - your server must send the Content-Length header with the size of the file.
Here is the javascript code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1" data-filename="filename.xml">Click to download</div>
<script>
$('#a1').click(function() {
var that = this;
var page_url = 'download.php';
var req = new XMLHttpRequest();
req.open("POST", page_url, true);
req.addEventListener("progress", function (evt) {
if(evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
}
}, false);
req.responseType = "blob";
req.onreadystatechange = function () {
if (req.readyState === 4 && req.status === 200) {
var filename = $(that).data('filename');
if (typeof window.chrome !== 'undefined') {
// Chrome version
var link = document.createElement('a');
link.href = window.URL.createObjectURL(req.response);
link.download = filename;
link.click();
} else if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE version
var blob = new Blob([req.response], { type: 'application/force-download' });
window.navigator.msSaveBlob(blob, filename);
} else {
// Firefox version
var file = new File([req.response], filename, { type: 'application/force-download' });
window.open(URL.createObjectURL(file));
}
}
};
req.send();
});
</script>
And here is an example for the php code you can use:
<?php
$filename = "some-big-file";
$filesize = filesize($filename);
header("Content-Transfer-Encoding: Binary");
header("Content-Length:". $filesize);
header("Content-Disposition: attachment");
$handle = fopen($filename, "rb");
if (FALSE === $handle) {
exit("Failed to open stream to URL");
}
while (!feof($handle)) {
echo fread($handle, 1024*1024*10);
sleep(3);
}
fclose($handle);
Note that I added a sleep to simulate a slow connection for testing on localhost.
You should remove this on production :)
Related
I create a PHP and ajax codes to create CSV file and download it when click a button. The PHP codes work fine, and for ajax I modify and set js codes according to Handle file download from ajax post all works good. but the downloaded csv file is empty while the file in custom file is correct. I use this codes in custom wordpress plugin.
function _exe_export_vendor_products(){
$current_user_id = esc_sql($_POST['c_user_id']);
$arg = array(
'limit' => 20,
'author' => $current_user_id
);
$product_list = wc_get_products($arg);
$title_array[] = array('ID', 'name', 'Price', 'SalePrice');
foreach($product_list as $_list){
$data_array[] = array($_list->get_id(), $_list->get_name(), $_list->get_price(), $_list->get_sale_price());
}
$final_array = array_merge($title_array, $data_array);
date_default_timezone_set("Asia/Tehran");
$current_date = date('Y-m-d-H-i');
$filename = "export-" . $current_user_id . "-" . $current_date . ".csv";
$f = fopen('https://sitename.com/export-import/' . $filename, 'w');
$delimiter=";";
foreach($final_array as $final_item){
fputcsv($f, $final_item, $delimiter);
}
fseek($f, 0);
header('Content-Type: text/csv; charset=UTF-8' );
header('Content-Encoding: UTF-8');
header('Content-Disposition: attachment; filename="'.$filename.'";');
readfile($filename);
fclose($f);
}
and JS codes:
jQuery.ajax({
type: "POST",
url: Ajax_object_dokan.ajax_url,
data:{
action: '_dokan_export_vendor',
c_user_id : current_user_id
},
xhrFields:{
responseType: 'blob'
},
success: function(blob, status, xhr){
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if(disposition && disposition.indexOf('attachment') !== -1){
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
});
I create file in https://sitename.com/export-import/filename.csv while the create tag a in JS has link to https://sitename.com/59360c8b-22a5-462b-9d7e-240e54a0c094.
How can I access to correct link to download file with ajax?
There are several issues in your code:
You use fopen() to access a URL with w mode. It can't work. You can only access a URL for reading.
Just use a path on the filesystem, for example:
$f = fopen($_SERVER['DOCUMENT_ROOT'] . '/export-import/' . $filename, 'w');
You call readfile() with just the file name, not the full path.
You call readfile() on the file before closing it. It may work but it's better to call fclose() first.
And you don't need to call fseek().
You set the Content-Encoding: UTF-8 header. That header is used to indicate compression (e.g. gzip), not
the character encoding. Remove it.
Also note that you don't need AJAX to download a file. You can just submit a form. All that complicated JS code is unnecessary.
Issue
I have a page where users can upload files with the help of FormData and an XMLHttpRequest.
Uploading the file works fine. But the upload.onprogress is only working when uploading from an HTTP connection.
HTTPS
HTTP
I've tested this on Heroku and on an Amazon EC2 instance. But it's always the same:
Progress is shown when uploading via HTTP
Progress event is never triggered when uploading via HTTPS
Javascript (Angular 7)
const xhr = new XMLHttpRequest();
let progress = 0;
/** THIS EVENT IS NOT WORKING WITH HTTPS */
xhr.upload.onprogress = (event: ProgressEvent) => {
if (event.lengthComputable) {
progress = 100 * (event.loaded / event.total);
}
};
xhr.responseType = 'json';
xhr.open('POST', `${API_URL}/${this.API_PATH}/upload`, true);
xhr.setRequestHeader('authorization', this.authService.getAuthToken());
xhr.send(payload);
xhr.onload = () => {
observer.next(xhr.response);
observer.complete();
};
Node.Js
const busboyBodyParser = require('busboy-body-parser');
app.use(busboyBodyParser())
const busboy = new Busboy({ headers: req.headers })
busboy.on('finish', async () => {
const fileData = req.files.file
const fileId = req.body.fileId
const params = {
Body: fileData.data,
Bucket: awsConfig.bucket,
ContentType: fileData.mimetype,
Key: fileId,
StorageClass: 'ONEZONE_IA',
}
awsConfig.s3.upload(params, (err, data) => { /* ... */ }
})
req.pipe(busboy)
What I've also tried
I also tried to use the .addEventListener syntax for listening for progress:
xhr.upload.addEventListener("progress", uploadProgress, false);
But this didn't work, either.
Source Code
Node.Js (server.js)
Node.Js (upload-file.js)
Angular Service (editor-file.service.ts)
Notes
Please note, that I have already asked a question about this topic. But I got no working answer and I really need this to work.
Old question: XHR upload onprogress Event not Working on HTTPS Connection
It's important to set Listener between:
xhr.open('POST'...);
...put you listener here....
xhr.send(data)
In this case it gonna work!
I'm doing just the same with one of my webapps but without any angular, just JS and PHP.
My xhr works like a charm and is looking like this:
var totalSize = 0;
var xhr = new XMLHttpRequest(); // den AJAX Request anlegen
xhr.open('POST', 'data/upload.php'); // Angeben der URL und des Requesttyps
xhr.upload.addEventListener("progress", handleProgress);
xhr.addEventListener("load", handleComplete);
and this my handleProgess method:
handleProgress = function(event){
var progress = totalProgress + event.loaded;
document.getElementById('progress').innerHTML = 'Aktueller Fortschritt: ' + ((progress - totalSize < 0) ? Math.floor(progress / totalSize * 10000) / 100 : 100) + '%';
}
As I've tried to reproduce this problem, I didn't face the same issue. Could you please check below simple Heroku app that I've created to test this specific problem? Also, if there is any missing part that I am not seeing, please inform me.
Heroku Test-Purpose App: https://erdsav-test-app.herokuapp.com/
Below is the JS code that I am tried to build on top of your code and it simply uploads the zip data and downloads it afterwards (cannot store on Heroku because of having Ephemeral filesystem) to ensure that the file is uploaded successfully;
import { Observable } from "../js/Observable.js";
document.addEventListener("DOMContentLoaded", function(event) {
var progressBar = document.getElementById("progress"),
fileNameSpan = document.getElementById("file_name"),
fileSizeSpan = document.getElementById("file_size"),
fileUploadComp = document.getElementById("file_upload"),
loadButton = document.getElementById("upload_button"),
displaySpan = document.getElementById("progress_display"),
fileDetails = document.getElementById("file_details"),
selectButton = document.getElementById("select_button"),
formData = null;
function hideElements(){
fileDetails.style.display = "none";
}
function showElements(){
fileDetails.style.display = "block";
}
function upload(payload, fileName){
return new Observable(observer => {
const xhr = new XMLHttpRequest();
let progress = 0;
/** THIS EVENT IS NOT WORKING WITH HTTPS */
xhr.upload.onprogress = (event => {
if (event.lengthComputable) {
progressBar.max = event.total;
progressBar.value = event.loaded;
progress = Math.floor((event.loaded / event.total) * 100);
displaySpan.innerText = progress + '%';
observer.next(progress);
}
});
xhr.upload.onloadstart = function(e) {
progressBar.value = 0;
displaySpan.innerText = '0%';
}
xhr.upload.onloadend = function(e) {
progressBar.value = e.loaded;
loadButton.disabled = false;
loadButton.innerHTML = 'Start Upload Process';
}
xhr.responseType = 'blob';
xhr.open('POST', "https://erdsav-test-app.herokuapp.com/upload.php", true);
xhr.send(payload);
xhr.returnedFileName = fileName;
xhr.onload = () => {
download(xhr.response, xhr.returnedFileName, "application/zip");
observer.next(100);
observer.complete();
};
});
}
function showUploadedFile(file){
var fileName = file.name;
var fileSize = file.size;
fileNameSpan.innerText = fileName;
fileSizeSpan.innerText = Math.floor(fileSize / 1000) + ' KB';
}
function buildFormData(file) {
if (formData) {
formData.append("file", file);
}
return formData;
}
hideElements();
if (window.FormData) {
formData = new FormData();
}
else{
alert("FormData is not supported in this browser!");
}
fileUploadComp.onchange = function(){
var file = fileUploadComp.files[0];
if(file){
showElements();
showUploadedFile(file);
}
else{
hideElements();
}
}
selectButton.addEventListener("click", function(e){
fileUploadComp.value = "";
hideElements();
fileUploadComp.click();
e.preventDefault();
});
loadButton.addEventListener("click", function(e) {
if(fileUploadComp.files !== undefined && fileUploadComp.files.length > 0){
this.disabled = true;
this.innerHTML = "Uploading. Please wait...";
var obs = upload(buildFormData(fileUploadComp.files[0]), fileUploadComp.files[0].name);
obs.subscribe(
function valueHandler(value){
console.log("UPLOADING");
if(value){
console.log(value);
}
},
function errorHandler(err){
console.log("THERE IS AN ERROR");
},
function completeHandler(){
console.log("COMPLETE");
}
);
}
else{
alert("No file is selected");
}
e.preventDefault();
});
});
PHP side
<?php
if ($_FILES['file']['error'] != $UPLOAD_ERR_OK) {
//writeLog($_FILES['file']['error']);
echo 'An error occurred!';
exit();
}
else {
$filePath = $_FILES['file']['tmp_name'];
$fileName = $_FILES['file']['name'];
if (file_exists($filePath)) {
ob_start();
$fileSize = readfile($filePath);
$content = ob_get_clean();
header('Content-Type: application/octet-stream;');
header("Content-Disposition: attachment; filename=\"" . $fileName . "\"");
header('Expires: 0');
header('Pragma: no cache');
header('Content-Length: ' . $fileSize);
echo $content;
}
else{
echo 'File is not found';
exit();
}
}
?>
HTML page source
<!DOCTYPE html>
<html lang="en">
<title>ProgressBar Progress Test</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="ProgressBar Progress Test">
<body>
<form method="post" enctype="multipart/form-data">
<input type="file" id="file_upload" accept="application/zip" style="width:0px" />
<button id="select_button">Choose File to Upload</button>
<progress id="progress" value="0"></progress>
<span id="progress_display"></span>
<button type="submit" id="upload_button">Start Upload Process</button>
</form>
<div id="file_details" style="display: none">
<h3>Selected File Details</h3>
<span id="file_name"></span><br>
<span id="file_size"></span>
</div>
<script type="module" src="js/Observable.js"></script>
<script src="js/download.js"></script>
<script type="module" src="js/main.js"></script>
</body>
</html>
Below image is captured by slowing the network to see the current percentage while uploading process continues;
Browsers used in testing;
Firefox Developer Edition 67.0b13 (64-bit/Up-to-date)
Google Chrome 74.0.3729.108 (64-bit/Up-to-date)
Now in 2022
The 2016's specifications are outdated, here is the new standard for XMLHttpRequest.
The upload is a getter that returns an XMLHttpRequestUpload object
The XMLHttpRequestUpload object implements the XMLHttpRequestEventTarget interface, which handles the onprogress event.
Now here's what MDN says about this:
Note: The spec also seems to indicate that event listeners should be attached after open(). However, browsers are buggy on this matter, and often need the listeners to be registered before open() to work.
Hi i am trying to upload an image with comments added to it into a database using php ajax and html.
here is the html part:
<form name="form1" enctype="multipart/form-data" action="">
<h2></h2>
<div class="form-group">
<textarea name="msg" class="form-control status-box" id="post" rows="3" cols="60" placeholder="What\'s on your mind?"></textarea>
<p>Upload an image.</p>
<input type="file" id="postPhoto" name="postPhoto" value="upload" placeholder="Upload Image">
</div>
</form>
<div class="button-group pull-right">
<p class="counter">200</p>
<a href="#" type="submit" onclick="submitChat()" class="post btn btn-primary">
Post</a>
</div><br><br>
this is what i have to the ajax which is on the same page as the html
<script>
function submitChat() {
var file = document.getElementById("postPhoto");
var formData = new FormData();
// alert(formData);
formData.append("file[]", file.files[0]);
if(form1.msg.value == '') {
alert('You must Enter a Post');
return;
}
var msg = form1.msg.value;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById('logs').innerHTML = xmlhttp.responseText;
console.log(xmlhttp.statusText);
}
}
xmlhttp.open('POST', 'userposts.php?msg='+msg, true);
xmlhttp.setRequestHeader("Content-type", "multipart/form-data");
xmlhttp.send(formData);
}
<script>
and this is the php part:
$msg = stripslashes(htmlspecialchars($_REQUEST['msg']));
if(isset($_FILES['postPhoto']['type'])) {
$imageData = "";
$validextensions = array("jpeg", "jpg", "png");
$temporary = explode(".", $_FILES['postPhoto']['name']);
$file_extension = end($temporary);
if((($_FILES['postPhoto']['type'] === 'image/png') || ($_FILES['postPhoto']['type'] == 'image/jpg') || ($_FILES['postPhoto']['type'] == 'image/jpeg')) && ($_FILES['postPhoto']['size'] < 2500000) && in_array($file_extension, $validextensions)) {
if($FILES['postPhoto']['error'] > 0) {
echo "return code: " . $_FILES['postPhoto']['error'] . "<br/><br/>";
}
else {
$imageData = mysqli_real_escape_string($connection, file_get_contents($_FILES["postPhoto"]["tmp_name"]));
}
}
}
$stmt = "INSERT INTO posts VALUES ('', '$uname', '$msg', '$imageData')";
$result = $connection->query($stmt);
the images do not seem to be getting sent to the php file idk how to go about fixing this. any help would be much appreciated.
Maybe Helpful,
You simply can't upload a file with pure Javascript ajax functions (at least not in a cross browser way, see this article for more information)
This is because XMLHttpRequest has no support for multipart/form-data, you can do tricks like using an iframe or use flash.
There are enough articles on the internet that explain this.(maybe helpful)
http://www.ajaxf1.com/tutorial/ajax-file-upload-tutorial.html
http://www.faqs.org/rfcs/rfc2388.html
Recomand
Use jQuery Ajax. which have easy lib. support and functions to upload images and submit/parse to destination files.
below sample jQuery AJAX code for demo
$(document).ready(function(){
$(document).on('submit','form[name="form1"]',function(e){
e.preventDefault();
var form = $(this)[0];
var formData = new FormData(form);
$.ajax({
url: 'Your url here',
data: formData,
type: 'POST',
// THIS MUST BE DONE FOR FILE UPLOADING
contentType: false,
processData: false,
// ... Other options like success and etc
success : function(data){
//Do stuff for ahed process....
}
});
});
});
Alright, So I have this script that uploads a file on drag and drop from the browser using HTML5.
$(function(){
var dropbox = $('#dropbox'),
message = $('.message', dropbox);
dropbox.filedrop({
// The name of the $_FILES entry:
paramname:'pic',
maxfiles: 50,
maxfilesize: 50,
url: 'post_file.php',
uploadFinished:function(i,file,response){
$.data(file).addClass('done');
// response is the JSON object that post_file.php returns
},
error: function(err, file) {
switch(err) {
case 'BrowserNotSupported':
showMessage('Your browser does not support HTML5 file uploads!');
break;
case 'TooManyFiles':
alert('Too many files! Please select 20 at most! (configurable)');
break;
case 'FileTooLarge':
alert(file.name+' is too large! Please upload files up to 10mb (configurable).');
break;
default:
break;
}
},
//// Called before each upload is started
// beforeEach: function(file){
// if(!file.type.match(/^image\//)){
// alert('Only images are allowed!');
//
// // Returning false will cause the
// // file to be rejected
// return false;
// }
// },
uploadStarted:function(i, file, len){
createImage(file);
},
progressUpdated: function(i, file, progress) {
$.data(file).find('.progress').width(progress);
}
});
var template = '<div class="preview">'+
'<span class="imageHolder">'+
'<img />'+
'<span class="uploaded"></span>'+
'</span>'+
'<div class="progressHolder">'+
'<div class="progress"></div>'+
'</div>'+
'</div>';
function createImage(file){
var preview = $(template),
image = $('img', preview);
var reader = new FileReader();
image.width = 100;
image.height = 100;
reader.onload = function(e){
// e.target.result holds the DataURL which
// can be used as a source of the image:
image.attr('src',e.target.result);
};
// Reading the file as a DataURL. When finished,
// this will trigger the onload function above:
reader.readAsDataURL(file);
message.hide();
preview.appendTo(dropbox);
// Associating a preview container
// with the file, using jQuery's $.data():
$.data(file,preview);
}
function showMessage(msg){
message.html(msg);
}
});
It runs on with the following post_file.php
<?php
// If you want to ignore the uploaded files,
// set $demo_mode to true;
$demo_mode = false;
$upload_dir = 'uploads/';
//$allowed_ext = array('jpg','jpeg','png','gif','doc','docx','pdf','xls','xlsx','pptx','ppt','rtf','txt','mp4','css','rar','zip','exe','mp3','wav');
if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
exit_status('Error! Wrong HTTP method!');
}
if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){
$pic = $_FILES['pic'];
//if(!in_array(get_extension($pic['name']),$allowed_ext)){
// exit_status('Only '.implode(',',$allowed_ext).' files are allowed!');
//}
if($demo_mode){
// File uploads are ignored. We only log them.
$line = implode(' ', array( date('r'), $_SERVER['REMOTE_ADDR'], $pic['size'], $pic['name']));
file_put_contents('log.txt', $line.PHP_EOL, FILE_APPEND);
exit_status('Uploads are ignored in demo mode.');
}
// Move the uploaded file from the temporary
// directory to the uploads folder:
if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
exit_status('File was uploaded successfuly!');
}
}
exit_status('Something went wrong with your upload!');
// Helper functions
function exit_status($str){
echo json_encode(array('status'=>$str));
exit;
}
function get_extension($file_name){
$ext = explode('.', $file_name);
$ext = array_pop($ext);
return strtolower($ext);
}
?>
Now the problem is I have a certain JSON url that when I open it sends a text message to a certain number. I'm trying to append that URL somewhere in the script so that it runs that url everytime an upload is made.
Any ideas?
$URL = "http://www.api.com/api.php?data=mydata";
$data = file_get_contents($URL);
This solves it.
I want to download multiple files on click of a button in jsp.
I am using the following code in the js to call one servlet twice.
var iframe = document.createElement("iframe");
iframe.width = iframe.height = iframe.frameBorder = 0;
iframe.scrolling = "no";
iframe.src = "/xyz.jsp?prodId=p10245";
document.getElementById("iframe_holder").appendChild(iframe);
var iframe2 = document.createElement("iframe");
iframe2.width = iframe2.height = iframe2.frameBorder = 0;
iframe2.scrolling = "no";
iframe2.src = "/xyz.jsp?prodId=p10243";
document.getElementById("iframe_holder").appendChild(iframe2);
In xyz.jsp i am calling the servlet which downloads the file from a path and send it on the browser.
Issue is that it is working safari,firefox but not in IE.
We cannot download multiple files with IE?
By design, non-user-initiated file downloads are blocked in IE. That inherently means that it should not be possible to download more than one file as the result of a single user-click.
I've used the following code to download multiple files in IE and Chrome
function downloadFile(url)
{
var iframe = document.createElement("iframe");
iframe.src = url;
iframe.style.display = "none";
document.body.appendChild(iframe);
}
function downloadFiles(urls)
{
downloadFile(urls[0]);
if (urls.length > 1)
window.setTimeout(function () { downloadFiles(urls.slice(1)) }, 1000);
}
You pass an array of URLs to the downloadFiles() function, which will call downloadFile() for each with a short delay between. The delay seems to be the key to getting it to work!
I had a similar need but also wanted the downloads to occur in a new window.
I created a js to download a list of files, and a php to do the actual file saving. I used the above as a starting point, and the PHP start from (okay, can't find the original source). I encode the passed URI so spaces in the file names don't cause troubles.
(function () {
"use strict";
var files = [], // Array of filename strings to download
newWindow, // New window to handle the download request
secondsBetweenDownloads; // Wait time beteen downloads in seconds
//
// Download a file using a new window given a URI
//
function downloadFile(uri) {
if (!newWindow) {
newWindow = window.open('',
'',
'width=1500 height=100');
}
if (newWindow) {
newWindow.location =
'saveAs.php?' +
'file_source=' + encodeURI(uri);
newWindow.document.title = "Download File: " + uri;
} else {
console.log("Unable to open new window. Popups blocked?");
}
}
//
// Download all files specified in the files[] array from siteName.
// Download the file at array position zero, then set a timeout for
// secondsBetweenDownloads seconds
//
function downloadFiles(siteName) {
var showTime = new Date();
console.log(
showTime.toTimeString().substring(0,8) +
" Starting download for: " + files[0]
);
// Skip any empty entries, download this file
if (files[0].length > 0) downloadFile(siteName + files.splice(0, 1));
if (files.length > 0) { // If more files in array
window.setTimeout(function () { // Then setup for another iteration
downloadFiles(siteName );
}, secondsBetweenDownloads * 1000); // Delay for n seconds between requests
} else {
newWindow.close(); // Finished, close the download window
}
}
//
// Set the web site name and fill the files[] array with the files to download
// then kick off the download of the files.
//
$(document).ready(function () {
var
siteName** = "http://www.mysteryshows.com/thank-you/";
secondsBetweenDownloads** = 35; // N seconds delay between requests
files = [
"show1.mp3",
"show2.mp3"
];
downloadFiles(siteName, files);
});
}());
The HTML for the page is simple. Basically any syntax-compliant page will do.
The saveAs.php page which the js file uses in the newWindow.location line is php only.
<?php
if (isset($_GET['file_source'])) {
$fullPath = $_GET['file_source'];
if($fullPath) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-Disposition: attachment;
filename=\"".$path_parts["basename"]."\""); // use 'attachment' to
// force a download
header("Content-type: application/pdf"); // add here more headers for
// diff. extensions
break;
default;
header("Content-type: **application/octet-stream**");
header("Content-Disposition:
filename=\"".$path_parts["basename"]."\"");
}
if($fsize) {//checking if file size exist
header("Content-length: $fsize");
}
$request = $path_parts["dirname"] . '/' .
rawurlencode($path_parts["basename"]);
readfile($request);
exit;
}
}
?>
I used rawurlencode on just the 'basename' portion of the URI to ensure it was a valid, encoded request.
It can be done by creating a blob using the file source URL. I have tested this with image and PDF files in IE 11.
if (navigator.msSaveBlob) {
var xhr = new XMLHttpRequest();
xhr.open('GET', file_url, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
navigator.msSaveBlob(blob, file_name);
}
}
xhr.onerror = function(e) {
alert("Error " + e.target.status + " occurred while receiving the document.");
}
xhr.send();
}
I got this idea when I came across this: Getting BLOB data from XHR request