jquery - 通过 jQuery 下载时 Zip 文件无效
问题描述
我正在开发一个 MVC 站点,以允许客户选择多个文档进行下载。我编写了允许他们单独生成任何交易的 PDF 的代码。新要求是允许选择行,然后生成一个包含所有生成的 PDF 的 zip 文件。
该网页在顶部设置了一个过滤器部分,之后表格中的事务和表格下方是分页控件。整个页面被包裹在一个表单中。由于我需要的数据已经在表格中,我将页面分成两种形式,一种用于过滤,一种用于下载。问题是分页控件是表单的一部分,需要过滤控件与页面一起提交。我将分页移到表格上方,这样它就可以成为过滤器表单的一部分,同时保留表格表单以用于我的多个 PDF 下载操作。这很好用,但我们有几个页面使用这种设置,所以为了保持网站统一,我必须将分页移动到所有这些页面的顶部。此外,营销对这种变化并不疯狂,但要了解这是否是必要的。
由于我无法在表单中嵌入表单,因此我决定为每一行的复选框添加属性,并使用 jQuery 遍历它们并提取我的操作所需的数据。这部分效果很好,我得到了我需要的所有数据,我把它们放到一个对象数组中,做 json 字符串化,我的控制器很高兴。我发现了这个问题:Download a file by jQuery.Ajax and try some answers。经过一些参数摆弄后,我让它返回二进制数据。我找到了一个解决方案,允许我的 ajax 调用下载它接收到的文件,并且看起来它正在工作,但是当我打开 zip 文件时,我得到“Windows 无法打开文件夹。压缩(压缩)文件夹 'c:\path\deliveries. zip' 无效”。
我知道该操作之前有效,因为它在连接为表单时有效,我只是在 _blank 目标上打开了表单操作。我应该提到我坚持使用 jQuery 1.11,因为这个应用程序很大,更新 jQuery 需要一周或更长时间来测试所有页面和功能。
这是控制器代码(工作正常)
[HttpPost]
public ActionResult GetMultiplePdfs(List<DeliveryPdfDownloadViewModel> deliveries)
{
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (var delivery in deliveries)
{
string file = $"Delivery-{delivery.CustomerNumber}-{delivery.siteNumber}-{delivery.Time.ToString("yyyyMMddhhmmss")}.pdf";
var url = $"/api/Delivery?customerNumber={delivery.CustNum}&shipToNumber={delivery.ShipToNum}&startTime={delivery.StartTime}";
var response = _client.GetAsync(url).GetAwaiter().GetResult();
var pdf = archive.CreateEntry(file);
using(var entryStream = pdf.Open())
using(var streamWriter = new StreamWriter(entryStream, Encoding.UTF8))
{
var byteArray = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
streamWriter.BaseStream.Write(byteArray, 0, byteArray.Length);
streamWriter.Flush();
}
}
}
logger.Info($"Successfully created zip file with {deliveries.Count()} PDF documents in it");
return File(memoryStream.ToArray(), "application/zip", "deliveries.zip");
}
}
这是 jQuery
$.ajax({
url: "@Url.Action("GetMultiplePdfs")",
type: "POST",
//dataType: 'application/zip',
data: { "deliveries": data },
//xhrFields: {
// responseType: "blob"
//},
success: function (result) {
let bobloblaw = new Blob([result]);
let a = document.createElement('a');
a.href = window.URL.createObjectURL(bobloblaw);
a.download = "deliveries.zip";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(a.href);
},
error: function () {
alert("Unable to download PDFs")
}
});
//subscribeRequest.done(function (data) {
// console.log(data);
//});
我包括了一些我尝试过的注释掉的行。在我摆脱 contentType 之前,我的操作无法识别我发送的 json。我的 ajax 调用失败,直到我删除了 dataType;我尝试使用 subscribeRequest 而不是成功,但结果相同。我尝试将 ajax 调用中的 responseType 设置为 blob。在创建我的 Blob 时,我尝试了 { type: "application/zip" },我还尝试了从上面的链接中找到的 "application/octetstream"。
解决方案
我让它工作了。我找到了另一个问题:Recifying a Zip file as response on AJAX request
我尝试了以下代码,它成功了!!!
fetch("@Url.Action("GetMultiplePdfs")", {
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
})
.then((response) => {
response.blob().then((blob) => {
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', downloadUrl);
link.setAttribute('download', 'file');
link.style.display = 'none';
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(link.href);
document.body.removeChild(link);
})
});
我不确定 fetch 和 ajax 之间有什么区别,但不知何故这正在返回我的文件。zip 文件打开,PDF 文件完好无损。
推荐阅读
- javascript - 在reactjs中滚动到页面顶部
- python - 如何提高 LSTM 模型的准确性(回归)
- javascript - 如何使用 socket.io 从 node.js 服务器在客户端(Web 浏览器)中显示实时数据?
- stm32f7 - 如何在 SDRAM 中写入 - STM32
- git - 检查分支更改是否被手动合并
- javascript - 在 React JS 的状态下设置 Java List 类型
- spring-boot - 创建实例时是否缓存了千分尺?
- python - 如何从 Python 获取 Binance 未来币数据
- ffmpeg - 如何通过ffmpeg的命令行读取sei
- angular - RxJS 订阅以改变订阅者数量