У меня старое устаревшее веб-приложение. Недавно мы переместили его со старого сервера Windows 2008 r2 на новый сервер Windows 2019, и обнаружилось несколько проблем. Я работал с большинством из них, но есть один, который все еще вызывает у меня некоторые проблемы. Это веб-приложение должно экспортировать данные в формате DataTable
в лист Excel для просмотра пользователем. Однако при экспорте файла Excel они получают это сообщение
Формат файла и расширение файла «Report.xls» не совпадают. Файл может быть поврежден или небезопасен. Если вы не доверяете его источнику, не открывайте его. Вы все равно хотите его открыть?
Если они нажмут "да", тогда он выдаст другое сообщение
Файл поврежден и не может быть открыт.
Не было никаких проблем со старым сервером r2 2008 года.
Я пытался изменить Response.ContentType = "application/vnd.xls";
на Response.ContentType = "application/vnd.ms-excel";
, а также Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
, и я все еще получаю то же самое Сообщения. Мне нужно предоставить лист Excel, и я не могу заплатить за пакет Excel.
Вот код, который генерирует файл Excel:
public void Create_Spreadsheet(string sheetField, string[] arrExcelColumns, DataTable table)
{
using (MemoryStream stream = new MemoryStream())
{
string pathToXsl = Server.MapPath(relToXsl);
string reportFileName = "Report.xls";
string fieldName = "Field";
string worksheetName = "Sheet";
string prevWorksheet = "";
DataView dv = new DataView();
DataTable dt = new DataTable();
dt = table;
// sort data for displaying with worksheets
dv = dt.DefaultView;
if (dv.Table.Columns.Contains(sheetField)) dv.Sort = sheetField;
DataTable dtSorted = dv.ToTable();
// get columns array
ArrayList arrColumns = new ArrayList();
for (int k = 0; k < dtSorted.Columns.Count; ++k)
{
if (Array.IndexOf(arrExcelColumns, dtSorted.Columns[k].ColumnName) >= 0)
arrColumns.Add(dtSorted.Columns[k].ColumnName);
}
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.Encoding = System.Text.Encoding.UTF8;
StringBuilder sb = new StringBuilder();
// Create the XmlWriter object and write some content.
XmlWriter xmlWriter = XmlWriter.Create(sb, settings);
xmlWriter.WriteStartDocument();
// Write our first XML header (root)
xmlWriter.WriteStartElement("Root");
if (dtSorted.Rows.Count > 0)
{
Regex rx = new Regex(@"^[a-zA-z_]+");
foreach (DataRow dr in dtSorted.Rows)
{
worksheetName = arrColumns.Contains(sheetField) && !String.IsNullOrEmpty(dr[sheetField].ToString()) ? dr[sheetField].ToString() : "New";
if (!rx.IsMatch(worksheetName)) worksheetName = "_" + worksheetName;
if (prevWorksheet != worksheetName)
{
// end write worksheet
if (!String.IsNullOrEmpty(prevWorksheet)) xmlWriter.WriteEndElement();
// begin write worksheet
xmlWriter.WriteStartElement(worksheetName);
}
// begin write record
xmlWriter.WriteStartElement("Record");
foreach (Object o in arrColumns)
{
fieldName = o.ToString();
//if (fieldName != sheetField) // don't display worksheet field
xmlWriter.WriteElementString(fieldName, dr[fieldName].ToString());
}
// end write record
xmlWriter.WriteEndElement();
prevWorksheet = worksheetName;
}
// end write last worksheet
xmlWriter.WriteEndElement();
}
else
{
// begin write worksheet
xmlWriter.WriteStartElement(worksheetName);
// begin write record
xmlWriter.WriteStartElement("Record");
foreach (Object o in arrColumns)
{
fieldName = o.ToString();
xmlWriter.WriteElementString(fieldName, "");
}
//xmlWriter.WriteElementString("Result", "No records found.");
// end write record
xmlWriter.WriteEndElement();
// end write worksheet
xmlWriter.WriteEndElement();
}
// end root
xmlWriter.WriteEndElement();
// Finilize the XML document by writing any required closing tag.
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
// Load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(pathToXsl);
// Create the writer.
XmlWriterSettings settings2 = new XmlWriterSettings();
settings2.Indent = true;
settings2.IndentChars = "\t";
XmlWriter writer = XmlWriter.Create(stream, settings2);
XmlReader xmlReader = XmlReader.Create(new StringReader(sb.ToString()));
xmlReader.MoveToContent();
// Execute the transformation.
xslt.Transform(xmlReader, writer);
writer.Close();
xmlReader.Close();
xmlWriter.Close();
// Convert the memory stream to an array of bytes.
byte[] byteArray = stream.ToArray();
// Send the XML file to the web browser for download.
Response.Clear();
//Response.AppendHeader("Content-Disposition", "filename=Report.xml");
//Response.AppendHeader("Content-Length", byteArray.Length.ToString());
//Response.ContentType = "application/octet-stream";
//Response.ContentType = "application/vnd.xls";
Response.ContentType = "application/vnd.ms-excel";
//Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", "attachment; filename=" + reportFileName);
Response.AppendHeader("Content-Length", byteArray.Length.ToString());
Response.BinaryWrite(byteArray);
Response.End();
}
}
Я не являюсь уверен, где дела идут не так, или что изменилось. Это новый сервер Windows 2019 (на котором не установлен офис), а код Asp .net / C# не имеет решения (он был создан в старом стиле "веб-сайта") , Любая помощь будет принята с благодарностью! дайте мне знать, если что-нибудь еще понадобится.
Edit:
с использованием библиотеки EPPlus и следующего кода:
public void ExportToExcel(DataTable dt, string FileName)
{
//create a new byte array
byte[] bin;
//create a new excel document
using (ExcelPackage excelPackage = new ExcelPackage())
{
//create a new worksheet
ExcelWorksheet ws = excelPackage.Workbook.Worksheets.Add(FileName);
//add the contents of the datatable to the excel file
ws.Cells["A1"].LoadFromDataTable(dt, true);
//auto fix the columns
ws.Cells[ws.Dimension.Address].AutoFitColumns();
//loop all the columns
for (int col = 1; col <= ws.Dimension.End.Column; col++)
{
//make all columns just a bit wider, it would sometimes not fit
ws.Column(col).Width = ws.Column(col).Width + 1;
var cell = ws.Cells[1, col];
//make the text bold
cell.Style.Font.Bold = true;
//make the background of the cell gray
var fill = cell.Style.Fill;
fill.PatternType = ExcelFillStyle.Solid;
fill.BackgroundColor.SetColor(ColorTranslator.FromHtml("#BFBFBF"));
//make the header text upper case
cell.Value = ((string)cell.Value).ToUpper();
}
//convert the excel package to a byte array
bin = excelPackage.GetAsByteArray();
}
//clear the buffer stream
Response.ClearHeaders();
Response.Clear();
Response.Buffer = true;
//set the correct contenttype
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
//set the correct length of the data being send
Response.AddHeader("content-length", bin.Length.ToString());
//set the filename for the excel package
Response.AddHeader("content-disposition", "attachment; filename=\"" + FileName + ".xlsx\"");
//send the byte array to the browser
Response.OutputStream.Write(bin, 0, bin.Length);
//cleanup
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
теперь выдает ошибку:
C: \ Users ... \ AppData \ Local \ Temp \ RoIFPfvQ.xlsx.part не удалось сохранить, поскольку исходный файл не может быть прочитан.
однако, если я пересылаю RDP на веб-сервер и go на веб-страницу, загружаю пакет и перемещаю его на локальный компьютер (поскольку Excel не находится на веб-сервере), файл открывается просто отлично. Что мне не хватает? где эта попытка создать xlsx.part
, и может ли быть содержимое удалено / удалено до того, как файл действительно будет сохранен / загружен?