3

我正在开发一个 Web 服务,用户可以在其中输入参数并可以选择以各种文件格式(xml、html(在屏幕上)、csv 等)返回数据。

如果服务器生成文件内容(因此没有实际文件),则返回文件的 URL 不是一种选择。那么如何做到这一点呢?我知道有 xml 属性表明元素中的数据是二进制的,但这不会触发浏览器将数据下载为文件。

Content DispositionXML/Web 服务有什么等价物吗?

在一个非常相关的说明上:

javascript/AJAX 可以触发浏览器下载文件吗?我知道仅 js 无法“生成”文件(从某种意义上说,浏览器会将字符串下载为具有给定文件名的文件)但是如果 ajax 函数调用脚本并且脚本回复有标题设置为下载?

我将尝试最后一部分,但想知道那里是否已经有任何可靠的信息。


更多细节:

首先,感谢所有回复的人。所有的答案都非常有帮助和教育意义。

我想我可能会尝试对这种情况进行更多解释,以将所有跨越答案的评论/担忧/建议联系起来。

我管理一个内部员工网站的项目。该项目主要处理进度查看和修改。至少有 4 个不同的 PHP 脚本查询 MySQL DB 以获取基本相同的数据。查询根据上下文略有不同。在一种情况下,它会提取按任务分组的每日时间表,在另一种情况下,它会查询整周的时间表并按人分组。在另一种情况下,它只查询一个人的每周日程安排。在某些情况下,它会输出数据,例如每人或每天或每个职位的小时总数,而在其他情况下,它只提供存储在数据库中的数据。

我开始对项目的某些方面感到内疚。显然,我可以将大量数据提取合并到一个包含的脚本中。我可能应该使用面向对象的 PHP 来处理结果。而且我更专注于解决这个问题,而不是确保数据安全可靠,并且确保数据库上的压力最小化和优化。我什至不确定如何真正知道查询是否已优化。

除了上面提到的内疚之外,我真的开始感到困惑了。在试图整理东西时,我发现自己陷入了一个结中,一个解决方案将一些工作正常的东西搞砸了。

所以,我认为一个好的解决方案是创建一个 Web 服务,它可以简化整个过程并迫使我对如何获取数据有一个逻辑(甚至是一个 API),并且对于任何试图当我最终不是首席开发人员时接管。此外,对于站点后端的升级和转移(有一天它可能在使用 Cold Fusion 的 Windows 服务器上,但我一想到我不寒而栗),以及可能想要连接的其他软件,这将使整个事情更加便携与数据库。

但问题是:

这个项目的整个起源是基于这样一个事实,即我们之前的调度解决方案是上传由我们使用的非常昂贵的企业级调度软件生成的非常丑陋和非语义的 HTML 报告。对于这个可怕的 HTML 报告和生成它的软件,我们遇到的第一个问题是没有.ics可以导入 Outlook 或 Google 日历的“icalendar”文件的选项。我的个人使命是想办法将那些糟糕的报告转换成 ics 文件,从而开始我为什么开始学习 PHP、regex 和 MySQL 的故事。

因此,如果您还没有感到无聊和睡着,我认为 Web 服务是简化和简化调度过程的最佳选择,但如果我最终不得不使用普通的 PHP/MySQL 来获取数据中最有价值的部分(日历文件)然后我倾向于放弃整个事情并继续解开结。

顺便说一句,我确实理解使用 Web 服务的脚本可以创建 ics 文件,并且当用户请求时可以简单地避免使用 AJAX。再次感谢所有让我更清楚这一点的人。我只希望 Web 服务在其末端尽可能处理 DB 返回的所有内容,以便在 HTML/JS/PHP 和数据库之间有一种清晰的分区感。

再次感谢!

4

6 回答 6

3

要让浏览器下载文件,您可以这样做:

window.location = "http://example.com/webservice-file-url";

并使用标题:

Content-Disposition: attachment; filename="filename.ext"

如果您希望用户在屏幕上查看和下载之间进行选择,只需使用条件:

if (requested_format == 'html') {
    //get an html version and show it on screen
    ajaxRequestForHTML();
} else {
    //download the file
    window.location = "http://example.com/webservice-file-url";
}
于 2009-08-16T17:36:11.513 回答
0

恐怕这行不通。AJAX 调用不会将其响应标头传递给浏览器。如果您更改标头,您唯一能做的就是您的 AJAX 调用可能会失败,因为标头将无法识别。

我看到的唯一解决方案是将 URL 返回到文件并打开将触发该下载的新 JS 窗口。

于 2009-08-16T13:18:55.130 回答
0

从 Web 服务返回一个字节数组。如果要将文件发送服务,则相同。

于 2009-08-16T13:25:48.683 回答
0

在典型的浏览器环境中,JavaScript 不能(出于安全原因)访问剪贴板或文件系统。对于一些讨论,请参阅clipboard-image-directly-save-in-to-client-side-using-javascript类似问题

也有例外,例如can-javascript-access-a-filesystem

于 2009-08-16T13:26:36.747 回答
0

Web 服务的意义在于它们不应该被浏览器直接访问——它们是供其他 Web 应用程序使用的 API。因此,您可能应该编写一个用户友好的前端,它调用 Web 服务并将数据作为 HTTP 响应中的文件提供。这将触发浏览器将其作为文件下载。

于 2009-08-16T13:38:52.337 回答
0

您确定希望这是一项网络服务吗?一个普通的网页怎么样,带有参数的表单字段,它只是将数据作为文件返回,并具有适当的内容处置?


根据您的更新,我很确定您不希望 Web 服务返回 .ics 文件。您想要的是一个脚本,它将使用查询字符串接受一些参数,然后使用“附件”内容处置返回文件。这将导致提示用户打开 .ics 文件。

现在,您还有一个好主意,可以重构几个类似的脚本以减少冗余和维护。但是,我担心你所说的每一个改变都会破坏一些东西。在开始重构之前,您至少需要为自己构建一个小型测试套件,最好是自动化的。这样,您将在每次小的更改后运行测试,看看您是否破坏了任何东西。这样,当你打破东西时,你只能打破一个小时的价值。

我建议使用包含的脚本或 PHP 具有的任何重用机制来重构 PHP 脚本(我不知道 PHP)。然后,您可能会发现某些通用代码将被适当地实现为 Web 服务。

于 2009-08-16T16:56:58.207 回答