【问题标题】:Manage JSON server response on form submit in case of error downloading file在下载文件出错的情况下管理表单提交时的 JSON 服务器响应
【发布时间】:2016-12-12 15:48:59
【问题描述】:

我有一个简单的 jQuery 代码,当用户单击按钮时,它会要求 PHP 服务器下载文件:

// Build a temp form
var jRestr = {sFitxer: sFitxer, bDownload: true};
var $form = $('<form></form>').attr('action', getMBD_URL()).attr('method', 'post');
// Add the one key/value
$form.append($("<input></input>").attr('type', 'hidden').attr('name', 'Consulta').attr('value', 'downLoadFile.php'));
$form.append($("<input></input>").attr('type', 'hidden').attr('name', 'UserName').attr('value', sessionStorage.usuari));
$form.append($("<input></input>").attr('type', 'hidden').attr('name', 'Token').attr('value', sessionStorage.token));
$form.append($("<input></input>").attr('type', 'hidden').attr('name', 'sFormat').attr('value', 'META'));
$form.append($("<input></input>").attr('type', 'hidden').attr('name', 'Modul').attr('value', sModul_glb));
$form.append($("<input></input>").attr('type', 'hidden').attr('name', 'sjRestr').attr('value', JSON.stringify(jRestr)));
//send request
$form.appendTo('body').submit().remove();

这就像一个魅力,但如果服务器遇到一些问题(找不到文件、权限被拒绝等),它会返回一个带有错误信息的 JSON,而不是请求的文件。

如何捕捉并以用户可读的格式显示?

我对可以使用哪种技术感到困惑,因为如果我使用 AJAX 调用,我不知道如何下载文件,如果我使用 HTML 提交调用,我将失去响应控制。

【问题讨论】:

  • 如果出现服务器错误,用户会被重定向到丑陋的(响应输出)页面?
  • @seak 你能告诉我们你的错误响应是什么样的吗?
  • 是的,同意@zayn-ali ...需要你的ajax代码的其余部分来显示你如何处理它的其余部分。可能最好在您的 php 代码中启动检查并发出一个 return 被您的 ajax 成功/捕获。
  • 这是服务器出错时的响应:{"sError":"File '2014-01-02 18.40.20.jpg' not found","lRedirectLogin":false}

标签: javascript php jquery error-handling download


【解决方案1】:

Ajax 不适用于下载文件。您可以改为获取文件名作为响应,然后重定向它

你的ajax成功函数应该是这样的。

document.location = "download.php?filename=" + response.fileName;

剩下的工作将由这两个标头的php响应完成。

下载.php

<?php 

$filename = $_GET['filename'];

header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename=' . $filename);

【讨论】:

  • 我知道如何处理错误的ajax调用,但是如何管理文件下载?据我所知(不多),如果我进行 Ajax 调用,当 PHP 返回 header("Content-Disposition: attachment; filename= ". $aRestr['sFitxer']); 而不是 header('Content-type: application/json'); 时,我会丢失下载,不是吗?
  • mmm 这是第一次调用 php 时所做的(当一切正常时)。做document.location = "path/to/the/process_file";是一个“魔术”吗?我可以放哪条路?最后一部分我输了
  • process_file 只是您的简单 php 文件,它只是将文件名附加到标题。假设它是 download.php,在其中你有你的代码来附加你从 ajax 调用的响应中获取的文件名。
  • 你的意思是不用在download.php中添加任何行就可以工作?
【解决方案2】:

主要问题是你不能用 ajax 下载文件,除非你把文件重定向到某个地方(用 JS window.location提交的表单)。

“正确”的方式

在您的服务器中创建一个端点以检查文件是否存在(或具有许可等)以便通过 ajax 轻松访问,一旦此请求执行成功响应,然后重定向(提交创建的表单)以获取文件.

var url = "new_endpoint_to_check_if_file_exists";

$.ajax({
    url: url,
    type: 'GET',
    success: function() {
        // Here the code to append your form and submit to download file.
    },
    error: function(er){
       console.log(er);
    }
});

另一方面,如果您想控制响应建议您使用 Ajax,请修改服务器上的逻辑工作方式。

丑陋的方式

如果您无法如前所述修改响应逻辑的工作方式,那么理论上您仍然可以下载文件,但您需要向同一个 URL 发出 2 次请求(提交表单的 2 次)。

// The form Data
var data = {
    'Consulta': 'downLoadFile.php',
    'UserName': sessionStorage.usuari,
    'Token': sessionStorage.token,
    'sFormat': 'META',
    'Modul': sModul_glb,
    'sjRestr' JSON.stringify(jRestr)
};
// The request URL 
var url = getMBD_URL();

$.ajax({
    url: ,
    type: 'POST',
    data: data
    success: function() {
        // If the "file exists or there's no server error"
        // Generate the file download again
        // Build the form and submit again ...
        var jRestr = {sFitxer: sFitxer, bDownload: true};
        var $form = $('<form></form>').attr('action', getMBD_URL()).attr('method', 'post');
        // Add the one key/value
        $form.append($("<input></input>").attr('type', 'hidden').attr('name', 'Consulta').attr('value', 'downLoadFile.php'));
        $form.append($("<input></input>").attr('type', 'hidden').attr('name', 'UserName').attr('value', sessionStorage.usuari));
        $form.append($("<input></input>").attr('type', 'hidden').attr('name', 'Token').attr('value', sessionStorage.token));
        $form.append($("<input></input>").attr('type', 'hidden').attr('name', 'sFormat').attr('value', 'META'));
        $form.append($("<input></input>").attr('type', 'hidden').attr('name', 'Modul').attr('value', sModul_glb));
        $form.append($("<input></input>").attr('type', 'hidden').attr('name', 'sjRestr').attr('value', JSON.stringify(jRestr)));
        //send request
        $form.appendTo('body').submit().remove();
    },
    error: function(er){
       console.log(er);
    }
});

这应该可以解决问题,但是,我会选择“正确”的方式。

【讨论】:

  • 丑的太丑了,因为需要 2 次转移。第一个选项,很好,但我非常细致,我总是希望在调用服务器时会出现问题,因为你检查了你之前能想象到的一切。如果它在 2 个呼叫中分开,则第二个呼叫可能会崩溃并且与最初的问题有相同的问题:-(
  • 有人告诉我,可以使用 window.navigator.msSaveOrOpenBlob(blob, name); 从 ajax 调用中获取文件。这是或类似的选择吗?或者它不适用于大文件?
猜你喜欢
  • 2018-11-26
  • 2020-02-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
相关资源
最近更新 更多