Javascript 向服务器发出JSON POST请求,接收二进制响应(Excel文件),如何下载?

Javascript 向服务器发出JSON POST请求,接收二进制响应(Excel文件),如何下载?,javascript,jquery,json,excel,rest,Javascript,Jquery,Json,Excel,Rest,我试图对发送JSON数据的服务器进行POST调用。服务器获取JSON数据,进行一些处理,然后返回一个Excel.xlsx作为响应。我希望浏览器打开“文件另存为”对话框供用户保存。我一直在寻找一个干净的解决方案来做到这一点。但这个问题的一个可能解决方案是,将Excel文件保存在服务器上,然后发回URL链接,然后打开iframe供用户下载。这对我来说是不可能的,因为用户可以在服务器上创建数千个Excel文件,而服务器的存储空间有限。我希望这个解决方案能在运行中。我看到的另一个解决方案建议将数据转换为

我试图对发送JSON数据的服务器进行POST调用。服务器获取JSON数据,进行一些处理,然后返回一个Excel.xlsx作为响应。我希望浏览器打开“文件另存为”对话框供用户保存。我一直在寻找一个干净的解决方案来做到这一点。但这个问题的一个可能解决方案是,将Excel文件保存在服务器上,然后发回URL链接,然后打开iframe供用户下载。这对我来说是不可能的,因为用户可以在服务器上创建数千个Excel文件,而服务器的存储空间有限。我希望这个解决方案能在运行中。我看到的另一个解决方案建议将数据转换为表单,然后使用表单提交。同样,这是不可能的,因为我的数据在数百行(如果不是数千行的话)的范围内

我的jQuery POST呼叫:

$.ajax({ type: 'POST', url: '/server/path', data: JSON.stringify(dataSent), processData: false, success: function(data, textStatus, jqXHR) { }, error: function(result, status, err) { }, contentType: 'application/json', dataType: 'application/vnd.ms-excel' }); $.ajax({ 键入:“POST”, url:“/server/path”, 数据:JSON.stringify(dataSent), processData:false, 成功:函数(数据、文本状态、jqXHR){ }, 错误:函数(结果、状态、错误){ }, contentType:'应用程序/json', 数据类型:“应用程序/vnd.ms excel” }); 在后端,我设置了以下内容:

响应标题(“内容类型”、“应用程序/vnd.ms excel”)

header(“内容处置”、“附件;文件名=\”导出.xlsx\“”)

强制浏览器打开“文件另存为…”对话框的最佳方式是什么


谢谢,

我不确定是否有办法通过JS接收二进制数据,然后启动下载


如果我负责这个任务,我会将方法更改为GET并生成文件(作为流),并返回带有适当标题的文件(内容配置、内容长度、内容类型)

我想办法解决这个问题。我不会通过POST调用强制浏览器打开“保存”对话框,而是通过POST调用生成文件,然后将文件临时存储在服务器上,返回文件名。然后对该文件使用GET调用“Content-Disposition:attachment;filename=filename1”。带有该标题的GET调用将强制浏览器始终打开“保存此文件”对话框

这实际上很容易做到

首先,下载文件。我将在TypeScript中使用
fetch
async
/
await
(您始终可以使用承诺链而不是
async
/
await
和/或使用XHR而不是
fetch
):

现在您有了blob,可以通过创建blob URL和隐藏链接将其传递给函数进行下载:

/**
 * Downloads a blob as a file.
 * 
 * TODO: Support iOS Safari, which doesn't support the "download" attribute.
 * 
 * @param name The name of the downloaded file
 * @param blob The blob to download
 */
export function saveBlobAsFile(name: string, blob: Blob) {
    // IE10 & IE11 Support, since they don't support the "download"
    // attribute on anchor tags.
    if (navigator.msSaveBlob) {
        navigator.msSaveBlob(blob, name);
        return;
    }

    // Create the URL and hidden anchor tag
    let $hiddenAnchorTag = $('<a style="display: none;"/>');
    let url = URL.createObjectURL(blob);

    // Set the attributes for the download
    $hiddenAnchorTag.attr('href', url);
    $hiddenAnchorTag.attr('download', name);

    // Insert the link and click to download
    $(document.body).append($hiddenAnchorTag);
    $hiddenAnchorTag[0].click();

    // Clean up after ourselves
    $hiddenAnchorTag.remove();
    URL.revokeObjectURL(url);
}
/**
*将blob作为文件下载。
* 
*TODO:支持iOS Safari,它不支持“下载”属性。
* 
*@param name下载文件的名称
*@param blob要下载的blob
*/
导出函数saveBlobAsFile(名称:string,blob:blob){
//IE10和IE11支持,因为它们不支持“下载”
//锚定标记上的属性。
if(navigator.msSaveBlob){
msSaveBlob(blob,名称);
返回;
}
//创建URL和隐藏的锚标记
让$hiddenAnchorTag=$('来获取服务器想要的文件名。我在网上找到了一些很好的正则表达式,它们可以很好地解决这个问题。里程数可能会有所不同,但我建议为此创建一个函数,并用一些不错的单元测试对其进行绑定
  • 这比试图将当前位置设置为文件的位置要好得多,因为它允许您在POST中包含更多细节,包括API密钥或类似的安全性,另外它还允许您干净地处理错误/异常,并知道操作何时完成(例如,当用户试图离开页面时,警告用户仍在等待下载)
  • Blob甚至支持在数据中进行切片,因此您可以通过获取单个切片(yayContent Range!)并将其组合成单个Blob,然后下载最终Blob来扩展此功能以下载大型文件,同时为用户提供一个良好的加载进度指示器
  • 您可以像使用其他URL一样使用Blob URL。它们指向资源,因此您可以将该URL传递给img标记、其他请求URL的库、src标记等
  • 在服务器上提供临时文件可能非常危险!如果需要使用该模式,则需要使用表或查找来抽象文件名,因此用户无法控制实际文件名或路径(在指定目录中使用UUID),并确保用户只能下载他们生成的文件。只需确保以下几件事(这不是一个全面的列表):
    • 用户不能指定保存到的任意路径
      • 它们可以通过数据库配置文件等进行保存
    • 用户不能指定要读取的任意路径
      • 他们可以读取您的数据库配置文件等
    • 文件名不能冲突。
      • 用户A生成一个名为“accounts_to_pay.csv”的文件。用户B同时生成一个同名文件(恶意或意外),现在用户A向用户B希望的任何人付款

  • 使用“在服务器上另存为Excel”的方法,您不应该将Excel文件保留在服务器上。您可以将该文件作为流程的一部分删除,或者定期清理一些后台流程。没有人希望您在服务器上永远保留1000个Excel文件。您为什么要承担POST(不是GET)在某种程度上,使用表单比Jquery帖子发送的数据量更有限?在下面,它们是相同的过程。GET在许多浏览器上被限制为特定的URL大小:如果OP有很多数据,它可能无法全部通过。是的,像Ti
    /**
     * Downloads a blob as a file.
     * 
     * TODO: Support iOS Safari, which doesn't support the "download" attribute.
     * 
     * @param name The name of the downloaded file
     * @param blob The blob to download
     */
    export function saveBlobAsFile(name: string, blob: Blob) {
        // IE10 & IE11 Support, since they don't support the "download"
        // attribute on anchor tags.
        if (navigator.msSaveBlob) {
            navigator.msSaveBlob(blob, name);
            return;
        }
    
        // Create the URL and hidden anchor tag
        let $hiddenAnchorTag = $('<a style="display: none;"/>');
        let url = URL.createObjectURL(blob);
    
        // Set the attributes for the download
        $hiddenAnchorTag.attr('href', url);
        $hiddenAnchorTag.attr('download', name);
    
        // Insert the link and click to download
        $(document.body).append($hiddenAnchorTag);
        $hiddenAnchorTag[0].click();
    
        // Clean up after ourselves
        $hiddenAnchorTag.remove();
        URL.revokeObjectURL(url);
    }