我有一个动态过滤的元素表,每个表都有一组按钮来操作它们。其中之一显示了用Razor生成的部分HTML以及元素的数据。
表条目:
foreach (var item in listado.Where(x => x.Raw != null)) {
<tr>
<td>@item.Id</td>
<td>@item.Usuario</td>
<td>@item.NIF_CIF</td>
<td>
@if (!(String.IsNullOrEmpty(item.Telefono)) && !(String.IsNullOrWhiteSpace(item.Telefono))) {
@item.Telefono
} else {
@Html.Raw("No disponible")}
</td>
<td>@Math.Round(item.Raw.PrecioTotal).ToString("0.##") €</td>
<td>@item.FechaCreacion.ToShortDateString()</td>
<td class="btn-group-sm" role="group">
<button class="eliminar btn btn-secondary btn-danger" data-itemid="@item.Id">Eliminar</button>
<button class="convertirPDF btn btn-secondary btn-info" data-itemid="@item.Id">PDF</button>
<button class="detalles btn brn-secondary btn-info" data-itemid="@item.Id">Detalles</button></td>
</tr>
<tr id="vistaDetalles@(item.Id)" hidden>
<td colspan="7">
@Html.Partial("_PresupuestoFinal", item)
</td>
</tr> }
我要使用的元素在行中生成
@Html.Partial("_PresupuestoFinal", item)
然后,使用jQuery,我为那些按钮提供了功能。 PDF按钮代码为:
$(".convertirPDF").on("click", function (id) {
var itemId = $(this).data('itemid');
var presupuesto = $('#content').html($(this).find('#vistaDetalles' + itemId).html());
Pdf(presupuesto);
});
function Pdf(presupuesto) {
presupuestoHTML = presupuesto;
$.ajax({
method: "GET",
url: 'DescargarPDF',
data: { presupuestoHTML: presupuesto },
cache: false,
async: true,
});
};
但是,每当我按下按钮时,我都会进入控制台:
TypeError: can't convert undefined to object
当我调用函数Pdf时参考该行。我要做的是选择该特定的html(对应于该元素的html)并将其转换为PDF文件。由于我没有足够的信息来知道错误在哪里,我在做什么错了?
顺便说一句,url: 'DescargarPDF
行指向控制器中的方法。
编辑
这是我要求的控制器方法:
public void DescargarPDF (string presupuestoHTML) {
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=" + "PDF.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
MemoryStream ms = new MemoryStream();
TextReader txtReader = new StringReader(presupuestoHTML);
// Creamos un objeto de clase itextsharp document
Document doc = new Document(PageSize.A4, 25, 25, 30, 30);
// Creamos un pdfwriter de itextsharp que lee el documento y dirige un stream XML a un archivo
PdfWriter oPdfWriter = PdfWriter.GetInstance(doc, ms);
// Creamos un trabajador para parsear el documento
HTMLWorker htmlWorker = new HTMLWorker(doc);
// Abrimos el documento y se lo pasamos al trabajador
doc.Open();
htmlWorker.StartDocument();
// Parseamos el presupuesto en html al documento
htmlWorker.Parse(txtReader);
// Cerramos el documento y el trabajador
htmlWorker.EndDocument();
htmlWorker.Close();
doc.Close();
var bPDF = ms.ToArray();
Response.BinaryWrite(bPDF);
Response.End();
}
脚本没有被击中。
第二次编辑
所以我得到了有关该错误的更多信息:
presupuestoHTML[toArray]
是引起错误的原因。不知道在哪里,或如何。
第三次编辑
好,所以我现在知道问题出在检索我想要的html的脚本上。我更改了这一行:
$(".convertirPDF").on("click", function (id) {
itemId = $(this).data('itemid');
presupuesto = document.documentElement.getElementsByTagName('vistaDetalles' + itemId);
Pdf(presupuesto);
});
现在控制台中的错误是:
TypeError: 'item' called on an object that does not implement interface HTMLCollection.
我会继续研究,希望这可以使问题更清楚。
第二次更新
我一直在努力,除了文件下载之外,我都能正常工作。我会解释:
这是脚本,它使用正确的数据命中了控制器方法。
$(".convertirPDF").on("click", function (id) {
var itemId = $(this).data('itemid');
// var presupuesto = $('#vistaDetalles' + itemId).html();
Pdf(itemId);
});
function Pdf(itemid) {
var id = itemid;
$.ajax({
method: "POST",
url: 'DescargarPDF',
data: { itemId: id },
cache: false,
async: true,
});
};
所以可行。这是我的控制器方法,我怀疑是引起问题的地方:
public FileResult DescargarPDF (int itemId) {
var presupuesto = ReglasNegocio.Fachada.Consultas.ObtenerPresupuesto(itemId);
var archivo = new Rotativa.PartialViewAsPdf("_PresupuestoFinal", presupuesto) { FileName = "Presupuesto_" + itemId + ".pdf" };
return File(archivo.FileName, "application/pdf");
}
那是我到目前为止的最后尝试。我也尝试过Rotativa的ActionAsPdf
,但在浏览器控制台上却获得了不是下载文件的数据流(我必须猜测是pdf文件)。我还尝试了其他选项,例如将文件转换为字节数组并进行流传输,但是由于我不想保存文件,因此该选项被丢弃(功能需要文件路径,我无法提供该路径,因为文件未保存,仍在内存中)。仍在努力。
答案 0 :(得分:1)
我请另一个question尝试解决未下载文件的问题,我明白了。
在进行任何操作之前,我都是通过ajax进行请求的,因为我认为这样做是一种很好的方法,但事实证明,有一种更简单的方法:不使用ajax。
因此,我删除了按钮的脚本和按钮本身,因此现在看起来像这样:
<a href="DescargarPDF/?itemId=@item.Id" target="_blank" class="btn btn-secondary btn-info">PDF</a>
它的外观与以前相同,但实际上是到我的控制器方法的链接,现在看起来像这样:
public FileResult DescargarPDF (int itemId) {
var presupuesto = ReglasNegocio.Fachada.Consultas.ObtenerPresupuesto(itemId);
var archivo = new Rotativa.PartialViewAsPdf("_PresupuestoFinal", presupuesto) { FileName = "Presupuesto_" + itemId + ".pdf", PageSize = Rotativa.Options.Size.A4 };
var binario = archivo.BuildFile(this.ControllerContext);
return File(binario, "application/pdf", archivo.FileName);
}
我知道在大多数情况下这不是一个有效的解决方案,因为我只是将ajax抛在了后面,但是还有很多其他问题,答案对他们有用,他们仍然使用ajax来管理请求。
不过,我希望这会有所帮助。谢谢大家。编码愉快。
更新
我刚刚找出了为什么我的PDF文件被放入控制台,请检查the other question,我对该特定问题做了一些解释。谢谢大家。
答案 1 :(得分:0)
您只能使用javascript: