如何将Excel文件与DNI图片打包到同一ZIP文件中?
问题
需要将存储运输商数据的表格导出为Excel格式,并与DNI图片打包成同一个ZIP文件。单独导出Excel或下载图片均正常,但合并打包时遇到问题:尝试将生成Excel的File()结果存入变量后添加到ZIP,提示“无法将Microsoft.AspNetCore.Mvc.FileContentResult转换为string”,转字节数组也未解决。
错误原因
File(stream.ToArray(), ...)返回的是FileContentResult类型的响应对象,它是ASP.NET Core用于返回文件的包装类,并非Excel文件的实际字节内容或文件路径,因此无法直接被ZipFile的AddEntry/AddFile方法识别。
解决方案
直接使用生成Excel时得到的字节数组,通过ZipFile的AddEntry方法将其添加到ZIP中,无需转换为FileContentResult。同时注意MemoryStream的复用问题,保存ZIP时需使用独立的流,避免和Excel的写入流冲突。
核心修正代码片段
dt.TableName = "Transportista"; using (XLWorkbook excel = new XLWorkbook()) { excel.Worksheets.Add(dt); // 生成Excel字节数组 byte[] excelBytes; using (MemoryStream excelStream = new MemoryStream()) { excel.SaveAs(excelStream); excelBytes = excelStream.ToArray(); } // 将Excel字节数组添加到ZIP string excelFileName = $"Transportista{DateTime.Now:yyyyMMddHHmmss}.xlsx"; zip.AddEntry(excelFileName, excelBytes); // 保存ZIP到独立的MemoryStream using (MemoryStream zipStream = new MemoryStream()) { zip.Save(zipStream); bytes = zipStream.ToArray(); } } return File(bytes, "application/zip", "Datos Transportista.zip");
完整修正后的后台代码
public FileResult DescargarDatosTransportista(string entrega) { try { DataTable dt = new DataTable(); string consulta; MySqlCommand cmd; List<PedidoViewModel> listaPedidos; byte[] bytes; string[] nombreImagen; using (ZipFile zip = new ZipFile()) { // 添加DNI图片到ZIP consulta = "SELECT ImgFrenteDni_tr, ImgDorsoDni_tr from transportista WHERE entrega_tr = @entrega"; listaPedidos = TraerDirectoriosImagenesEntrega(consulta); foreach (var lista in listaPedidos) { nombreImagen = lista.getImgFrenteDni_tr().Split("/"); var archivo_nombre = nombreImagen[5]; var archivo_arregloBytes = System.IO.File.ReadAllBytes("wwwroot" + lista.getImgFrenteDni_tr()); zip.AddEntry(archivo_nombre, archivo_arregloBytes); nombreImagen = lista.getImgDorsoDni_tr().Split("/"); archivo_nombre = nombreImagen[5]; archivo_arregloBytes = System.IO.File.ReadAllBytes("wwwroot" + lista.getImgDorsoDni_tr()); zip.AddEntry(archivo_nombre, archivo_arregloBytes); } // 查询运输商数据并生成Excel using (MySqlConnection cn = new MySqlConnection($"datasource={server};database={database};username={user};password={password};")) { consulta = "SELECT entrega_tr, numTramite_tr, nombre_tr, apellido_tr, sexo_tr, documento_tr, ejemplar_tr, fechaNac_tr, fechaEmision_tr, cod_tr from transportista WHERE entrega_tr = @entrega"; cmd = new MySqlCommand(consulta, cn); cmd.Parameters.AddWithValue("@entrega", entrega); cmd.CommandType = CommandType.Text; cn.Open(); using (MySqlDataAdapter da = new MySqlDataAdapter(cmd)) { da.Fill(dt); } } dt.TableName = "Transportista"; using (XLWorkbook excel = new XLWorkbook()) { excel.Worksheets.Add(dt); // 获取Excel字节数组 byte[] excelBytes; using (MemoryStream excelStream = new MemoryStream()) { excel.SaveAs(excelStream); excelBytes = excelStream.ToArray(); } // 添加Excel到ZIP string excelFileName = $"Transportista{DateTime.Now:yyyyMMddHHmmss}.xlsx"; zip.AddEntry(excelFileName, excelBytes); } // 生成ZIP字节数组并返回 using (MemoryStream zipStream = new MemoryStream()) { zip.Save(zipStream); bytes = zipStream.ToArray(); } } return File(bytes, "application/zip", "Datos Transportista.zip"); } catch (Exception ex) { // 按需处理异常,例如返回错误提示或空结果 return null; } }
关键说明
- 避免将Excel的
MemoryStream直接用于保存ZIP,必须使用独立的流,防止流的位置和内容混乱。 - 使用
AddEntry方法传入文件名和字节数组,是将内存内容直接添加到ZIP的正确方式,无需生成物理文件。 - 对
DateTime.Now使用格式化字符串生成文件名,避免重复或包含特殊字符。
内容的提问来源于stack exchange,提问作者Bilbit Bolson
相关产品推荐
相关产品推荐

