我有一个奇怪的情况:我从 Postgres 数据库中获取数据,然后从这些数据中,我使用 Grid.js 在网站中创建了一个表。每行都有一个“下载”按钮,该按钮从该表条目中获取 2 个参数并将它们发送到一个函数。最初,该函数将向 php 文件发出 XHR 请求,该文件从另一个数据库获取文件,创建一个 ZIP 文件,并将其发送给用户,并使用readfile()
.
我现在发现这是不可能的。出于安全原因,XHR 不允许下载。我可以做一些事情window.location
来调用 PHP 文件并获取下载,但是我正在处理数百个文件,所以我不能编写数百个 PHP 文件来单独获取数据。我可以,但是维护和管理所有这些文件会非常困难,而且感觉不专业。
现在,我可以:
- 使用 POST 将数据从 JS 发送到 PHP;
- 使用这两个变量,从另一个 Postgres 服务器获取数据;
- 使用这些文件并创建一个 ZIP 文件(由于存储限制,ZIP 文件不能永久存储在服务器中。服务器中的 cronjob 最终会清理文件)
我需要:
- 将 ZIP 发送给用户;
- 保持尽可能简单的代码,我可以提供 2 个变量并且它可以正常工作,而不需要为每个表行创建一个 PHP 文件(如果这有意义的话)
当前代码是:
- Javascript
const getData = (schema, table) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', 'php/get_data.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
let packg = {
schema: schema,
table: table
};
const packgJSON = JSON.stringify(packg);
// Vanilla JS XHR requires this formatting to send the data
const data = new URLSearchParams({'content': packgJSON});
xhr.send(data);
};
- PHP
<?php
// File with connection info
$config = include('config.php');
// Connection info
$host = $config['host'];
$port = $config['port'];
$database = $config['database'];
$username = $config['username'];
$password = $config['password'];
// POST reception
$packg = json_decode($_POST['content']);
$schema = $packg->schema;
$table = $packg->table;
// File info and paths
$filename = $table;
$rootDir = "tempData/";
$fileDir = $filename . "/";
$filePath = $rootDir . $fileDir;
$completeFilePath = $filePath . $filename;
$shpfile = $filename . ".shp";
$zipped = $filename . ".zip";
$zipFile = $completeFilePath . ".zip";
// Function to send the file (PROBLEM - THIS DOES NOT WORK WITH XHR)
function sendZip($zipFile) {
$zipName = basename($zipFile);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=$zipName");
header("Content-Length: " . filesize($zipFile));
ob_flush();
flush();
readfile($zipFile);
};
// Send the zip if it's already available (NOT PROBLEMATIC)
if (file_exists($zipFile)) {
sendZip($zipFile);
};
// Get shapefile, zip it and send it, if not available (NOT PROBLEMATIC)
if (!file_exists($zipFile)) {
// Get files
exec("mkdir -p -m 777 $filePath");
exec("pgsql2shp -h $host -p $port -u $username -P $password -g geom -k -f $completeFilePath $database $schema.$table");
// ZIP the files
$zip = new ZipArchive;
if ($zip -> open($zipFile, ZipArchive::CREATE) === TRUE) {
$handlerDir = opendir($filePath);
// Iterates all files inside folder
while ($handlerFile = readdir($handlerDir)) {
// If the files are indeed files, and not directories
if (is_file($filePath . $handlerFile) && $handlerFile != "." && $handlerFile != "..") {
// Zip them
$zip -> addFile($filePath . $handlerFile, $fileDir . $handlerFile);
};
};
// Close the file
$zip -> close();
};
sendZip($zipFile);
};
?>