考虑一个允许用户存储文件的站点(仅pdf,docx,jpeg,png,gif)。 html的一部分:
<ul>
<li><a href="../folder/lola.doc" target="_blank">lola.doc</a></li>
<li><a href="../folder/lola.pdf" target="_blank">lola.pdf</a></li>
<li><a href="../folder/lola.jpeg" target="_blank">lola.jpeg</a></li>
<li><a href="../folder/lola.docx" target="_blank">lola.docx</a></li>
</ul>
当用户单击以上任何一项时,文件将打开或出现一个保存Dialpg。很好。
现在,我希望用户能够选择其中一些文件(位于服务器上)。文件将被压缩并回显给用户,并提示保存。我不能在上面使用,所以我有这个选项:
html:
<select class="multiple_select " multiple>
<option value="../folder/lola.doc">lola.doc</option>
<option value="../folder/lola.pdf">lola.pdf</option>
<option value="../folder/lola.jpeg">lola.jpeg</option>
<option value="../folder/lola.docx">lola.docx</option>
</select>
<button id="btn" type="button">Download</button>
js:
js:
$('#btn').on('click', function() {
var options_selected = $('select').find('option:selected');
options_selected_le = options_selected.length;
var i;
var options_selected_arr = [];
var options_names_arr = [];
for (i=0; i<options_selected_le; i++) {
options_selected_arr.push(options_selected.eq(i).val());
options_names_arr.push(options_selected.eq(i).text());
}
var fd = new FormData();
fd.append('zipname', zipname);
fd.append('options_selected_arr', JSON.stringify(options_selected_arr));
fd.append('options_names_arr', JSON.stringify(options_names_arr));
$.ajax({
url: 'download_multiple_files.php',
type: 'post',
data: fd,
cache: false,
contentType: false,
processData: false,
beforeSend: function(xhr) {
xhr.setRequestHeader("X-Download", "yes");
},
success: function(response){
alert(response); //I am sure this is wrong
// Do I need js to handle zip file here. I guess php should automatically do this
}
});
});
<?php
session_start();
require 'server_conn.php'; // for connection and holds test_input function
// do some security checks ...
$zipname = 'file.zip';
$arr = json_decode($_POST['options_selected_arr']);
$file_arr = [];
foreach ($arr as $obj) {
array_push($files_arr, test_input($obj));
}
$arr = json_decode($_POST['options_names_arr']);
$files_names_arr = [];
foreach ($arr as $obj) {
array_push($files_names_arr, test_input($obj));
}
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
for ($i=0; $i<$c; $i++) {
$zip->addFile($file_arr[$i], $files_names_arr[$i]);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Length: ' . filesize($zipname));
header('Content-Disposition: attachment; filename="file.zip"');
readfile($zipname);
unlink($zipname);
?>
来自服务器的响应是随机的,没有错误指示。我怀疑我的php有缺陷。
答案 0 :(得分:0)
我已经使用2种方法解决了这个问题: 方法1: 没有php的JSZip(每个选择选项已经包含文件路径作为值) 这种方法的优点:它不会在服务器上存储新的zip文件,因此存储不是问题。 我相信使用Blob还可以压缩大型文件,最大大小我不知道。 要使用此方法,需要下载Filesaver,jszip和jszip实用程序,并将以下行添加到html文档正文中
<script src="../js/lib/jszip.min.js"></script>
<script src="../js/lib/jszip-utils.min.js"></script>
<script src="../js/lib/FileSaver.js"></script>
js脚本利用了Promisejs,我之前没有研究过(但是现在可以使用)。下面是js:
$('#btn').on('click', function() {
function urlToPromise(url) {
return new Promise(function(resolve, reject) {
JSZipUtils.getBinaryContent(url, function (err, data) {
if(err) {
reject(err);
} else {
resolve(data);
}
});
});
}
var options_selected = $('select').find('option:selected');
options_selected_le = options_selected.length;
var zipname = 'file.zip';
var Promise = window.Promise;
if (!Promise) {
Promise = JSZip.external.Promise;
}
var i;
var zip = new JSZip();
for (i=0; i<options_selected_le; i++) {
var url = options_selected.eq(i).val();
var filename = options_selected.eq(i).text();
zip.file(filename, urlToPromise(url), {binary:true});
}
zip.generateAsync({type:"blob"}).then(function callback(blob) {
//see FileSaver.js
saveAs(blob, zipname);
//alert('success');
}, function (e) {
alert('Error zipping file(s). Retry');
});
});
方法2: 使用js和PHP: 首先在服务器上创建一个文件夹来保存zip文件,我将文件夹命名为“ archive” 这就是为什么我可能不赞成这种方法的原因。 新的js:
$('#btn').on('click', function() {
var options_selected = $('select').find('option:selected');
options_selected_le = options_selected.length;
var zipname = 'file.zip';
var fd = new FormData();
fd.append('zipname', zipname);
fd.append('options_selected_arr', JSON.stringify(options_selected_arr));
fd.append('options_names_arr', JSON.stringify(options_names_arr));
$.ajax ({
url: 'download_multiple_files.php',
type: 'post',
data: fd,
cache: false,
contentType: false,
processData: false,
success: function(response){
window.location = response;
}
});
});
新的php:
<?php
session_start();
// connect to server, scan input data and do some security checks ...
$zipname = 'file.zip';
$arr = json_decode($_POST['options_selected_arr']);
$file_arr = [];
foreach ($arr as $obj) {
array_push($files_arr, test_input($obj));
}
$arr = json_decode($_POST['options_names_arr']);
$files_names_arr = [];
foreach ($arr as $obj) {
array_push($files_names_arr, test_input($obj));
}
$zip = new ZipArchive();
$path = '/archive/'.$zipname;
if ($zip->open($path, ZipArchive::CREATE)!==TRUE) {
echo 'Cannot zip files'; die;
}
$c = count($file_arr);
for ($i=0; $i<$c; $i++) {
$zip->addFile($file_arr[$i], $files_names_arr[$i]);
}
$zip->close();
echo $path;
mysqli_close($conn);
?>
这将强制显示保存对话框。我对这种方法有两个尚待解决的挑战: 禁止打开新窗口 出现保存对话框,下载为文件名,但没有扩展名.zip。因此,用户应输入.zip及其名称。我希望将计算出的zip文件名显示在“保存”对话框中