简体   繁体   English

如何将文件传递给PHP并通过一个脚本下载回去?

[英]How to pass a file to PHP and download it back in one script?

I'm sorry, I'm pretty sure I've seen a similar question one day but I can't find it and I can't figure it out on my own. 很抱歉,我很确定有一天我也遇到过类似的问题,但是我找不到它,也无法自己解决。

I need to be able to save a JSON file locally, but the download attribute and the File API aren't browser-friendly enough so I decided to send the JSON string to the server and have the server send me the file with the right HTTP headers to make the browser download it. 我需要能够在本地保存JSON文件,但是download属性和File API不够浏览器友好,因此我决定将JSON字符串发送到服务器,并让服务器使用正确的HTTP向我发送文件标头,以使浏览器下载它。

But I don't want to leave the page. 但是我不想离开页面。 From what I can see, AJAX can't trigger file download (or I've been trying it wrong), so I'd have to use a hidden HTML form which would send the data through POST. 据我所知,AJAX无法触发文件下载(或者我尝试做错了),因此我不得不使用隐藏的HTML表单,该表单将通过POST发送数据。 How can I send POST data to a php file which will return a file to download without leaving the page? 如何将POST数据发送到php文件,该文件将返回文件以下载而不离开页面?

What I've tried in AJAX: 我在AJAX中尝试的方法:

sd.requestDownload = function() {
  if(sd.request && sd.request.readyState != 0) {
    return false; // there's already a request in progress
  }

  sd.request = sd.createRequest();

  sd.request.onreadystatechange = function() {
    if(sd.request.readyState == 4 && (sd.request.status == 200 || sd.request.status == 0)) {
      // download?
    } else if(sd.request.readyState < 4) {
      // show loading screen here
    }
  }

  sd.request.open("POST", "save.php", true);
  sd.request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  sd.request.send("json=" + encodeURIComponent(sd.saveToJSON()));
};

The PHP code: PHP代码:

<?PHP

session_start();

$file = '';

if(isset($_POST['json'])) {
  header('Content-Type: application/json; charset=utf-8');
  header('Content-Disposition: attachment; filename=plan.json');
  $file = $_POST['json'];
} else if(isset($_POST['file'])) {
  header('Content-Type: application/octet-stream; charset=utf-8');
  header('Content-Disposition: attachment; filename=plan');
  $file = $_POST['file'];
} else {
  http_response_code(400);
  $file = '400 ERROR: NO FILE RECEIVED';
}

header('Expires: Sun, 01 Jan 2015 00:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');

echo htmlentities($file);

I've figured something which works, but IE shows an error about missing a doctype in the debugger. 我已经找到了可行的方法,但是IE显示了有关在调试器中缺少doctype的错误。 My solution involves creating a form in JS without appending it to the page. 我的解决方案涉及在JS中创建表单 而不将其附加到页面。 If the HTTP header says that it's a file attachment, the page won't change. 如果HTTP标头表明它是文件附件,则页面不会更改。 I've seen people talk about setting the target to an iframe or to "_blank" for extra saftey, but Chrome considers such calls to be popups, so it blocks them and won't send the POST request again if the user clicks on "show popup". 我见过有人谈论将目标设置为iframe或将“ _blank”设置为额外的安全提示,但是Chrome认为此类调用是弹出式窗口,因此它将阻止它们,并且如果用户单击“显示弹出窗口”。

EDIT: it seems IE ignores the call to submit() if the form isn't on the page. 编辑:如果表单不在页面上,似乎IE会忽略对commit()的调用。 I modified the code in consequence. 因此,我修改了代码。

This question is what gave me the idea: JavaScript post request like a form submit 这个问题是什么让我产生了这个想法: JavaScript发出的请求就像表单提交一样

PHP 的PHP

if(isset($_POST['filecontent'])) {
  header('Content-Type: application/octet-stream; charset=utf-8');
  if(isset($_POST['filename'])) {
    header('Content-Disposition: attachment; filename=' . preg_replace('/[^a-zA-Z0-9_\.]+/', "", $_POST['filename']));
  } else {
    header('Content-Disposition: attachment;');
  }
  $file = $_POST['filecontent'];
} else {
  http_response_code(400);
  $file = '400 ERROR: NO FILE RECEIVED';
}

header('Expires: Sun, 01 Jan 2015 00:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');

echo $file;

JS JS

download = function(filename, filecontent) {
  var form = document.createElement("form");
  form.setAttribute("method", "post");
  form.setAttribute("action", "save.php");
  form.style.display = "none";
  var i = document.createElement("input");
  i.setAttribute("type", "hidden");
  i.setAttribute("name", "filename");
  i.setAttribute("value", filename);
  form.appendChild(i);
  i = document.createElement("input");
  i.setAttribute("type", "hidden");
  i.setAttribute("name", "filecontent");
  i.setAttribute("value", filecontent);
  form.appendChild(i);

  document.body.appendChild(form);
  form.submit();
  document.body.removeChild(form);
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM