下载文件缺少插入的数据

问题描述 投票:0回答:2

我支持的旧网站的一个功能是能够下载数据提取。部署应用程序后,提取似乎已成功完成,但仅下载的文件在任何选项卡中都不包含任何数据。其逻辑是,根据从数据库读取的数据填充 10 张空白的 Excel 模板(仅包含标题)并将其插入到选项卡中。

// Copy the template to the relevant folder
const string templateFilename = "DataExtractTemplate.xlsx";
var templateFullPath = Server.MapPath($"~/Administration/Templates/{templateFilename}");
var templateFileInfo = new FileInfo(templateFullPath);
var temporaryFile = Server.MapPath($"~/Administration/ExtractOutput/{templateFilename}");
templateFileInfo.CopyTo(temporaryFile, true);
templateFileInfo = new FileInfo(temporaryFile) { IsReadOnly = false };
// Download the file to the user's downloads folder
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=DataExtract.xlsx");
Response.AddHeader("Content-Length", templateFileInfo.Length.ToString());
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.TransmitFile(templateFileInfo.FullName);
Response.Flush();
Response.Close();
Response.End();
templateFileInfo.Delete();

我已确认数据正在加载到数据表中,并且就其显示而言,每一行都插入到复制模板的每个工作表中,但我最终得到的文件与我开始使用的文件相同,即一个空模板。我已确认文件已正确复制到服务器上,并且使用下面的代码从数据填充参数。

// Get the relevant OleDbType based on the column type
internal static OleDbType GetOleDbType(string systemType)
{    
    OleDbType returnType;
    switch (systemType)
    { 
         case "Double":
         case "Int32":
            returnType = OleDbType.Numeric;
            break;
        default:
            returnType = OleDbType.VarChar;
            break;
    }

    return returnType;
}

// Create delimited list of column names
var columnParams = dataTable.Columns.Cast<DataColumn>()
    .Aggregate(string.Empty,
               (current,
                       column) => current + $"@{column.ColumnName},");
columnParams.TrimEnd(',');
// Create parameters for each row and insert into the worksheet
int insertedRows = 0;
foreach (DataRow dataRow in dataTable.Rows)
{
    oleCmd.Parameters.Clear();
    oleCmd.CommandText = $"INSERT INTO [{tabName}$] VALUES ({parameterValues})";
    var columnCount = 0;
    var parameters = new List<OleDbParameter>();
    foreach (DataColumn column in dataTable.Columns)
    {                                      
        var dataColumnName = column.ColumnName;
        var dataTypeName = column.DataType.Name;                    
        var dataRowItemValue = dataRow[columnCount];                    
        var isItemNull = string.IsNullOrEmpty(dataRowItemValue.ToString());
        var parameter = new OleDbParameter { ParameterName = $"${dataColumnName}", SourceColumn = dataColumnName, OleDbType = GetOleDbType(dataTypeName) };
        if (!isItemNull)
        {            
            switch (dataTypeName)
            {
                case "Double":
                case "Int32":
                case "DateTime":
                    parameter.Value = Convert.DBNull;
                    break;
                default:
                    parameter.Value = string.Empty;
                    break;
            }
        }
        else
        {            
            var cellValue = dataRow.ToString();
            switch (dataTypeName)
            {
                case "Double":
                    parameter.Value = double.Parse(cellValue);
                    break;
                case "Int32":
                    parameter.Value = int.Parse(cellValue);
                    break;
                default:
                    parameter.Value = cellValue;
                    break;
            }
        }
    
        parameters.Add(parameter);
    }

    oleCmd.Parameters.AddRange(parameters.ToArray());
    insertCount += oleCmd.ExecuteNonQuery();
    rowCount++;
}

每次 ExecuteNonQuery 都成功,即返回 1,但没有数据写入模板。奇怪的是,它似乎适用于使用几乎所有相同代码的类似提取,但输出已损坏。此提取有 21 列数据,共 4-500 行,这是我打开它时收到的错误:

asp.net response oledb outputstream
2个回答
0
投票

最好的猜测是数据没有被拉到服务器上。代码看起来不错,并且如前所述,在本地测试期间可以正常工作。任何数据拉取和下载是否在服务器上有效?

我的意思是,显然生产中使用的连接路径将有很大的不同。您可能想使用一些按钮(例如“数据库连接测试”)向应用程序添加一些测试页面。或者使用拉动行的按钮,并将行数推入同一页面上的文本框中。

请记住,运行的生产 IIS 服务器版本必须与已安装的 Access 数据引擎版本的位大小相匹配。因此,如果您使用 Access x32,请启用 x32 位应用程序池。我

我也永远不会使用任何 cpu,而是强制项目以 x32 位运行,或强制项目以 x64 位运行。如前所述,如果强制项目以 x64 位运行,则必须在服务器上安装 x64 位版本的 Access 数据引擎。

那么,临时文件的路径是什么?哎呀,以前的一些代码是否将该文件放置在临时文件夹中?我不太相信将 Excel 文件放在 Windows 临时文件夹中是一个好主意。我将在项目中创建一个文件夹,并使用 sever.mappath() 获取该文件位置,因此该 Excel 文件应该放置在更好的文件夹位置,因为在托管服务器上,您可能拥有一些权限和限制对于 Windows 文件夹。


0
投票

我最初认为这是编码端的问题 - 将空白模板复制到新位置时,空白模板的路径被传回,而不是复制的文件。

const string templateFilename = "DataExtractTemplate.xlsx";
var templateFullPath = Server.MapPath($"Templates/{templateFilename}");
var templateFileInfo = new FileInfo(templateFullPath);
var temporaryFile = Server.MapPath($"ExtractOutput/{templateFilename}");
templateFileInfo.CopyTo(temporaryFile, true);
templateFileInfo = new FileInfo(templateFileInfo) { IsReadOnly = false };
return templateFileInfo.FullName;

倒数第二行应该是:

templateFileInfo = new FileInfo(temporaryFile) { IsReadOnly = false };

我还按照建议将 Windows 临时文件夹替换为项目内的文件夹,因此 C:\Windows\Temp 不需要权限,但仍然遇到相同的问题。
这是最新的日志:
2024 年 2 月 2 日 12:57 以 Martin Swanston 身份运行
连接字符串:Provider=Microsoft.ACE.OLEDB.12.0;数据 源=C:\Webs\web-n-rsgpsd\Administration\ExtractOutput\DataExtractTemplate.xlsx;扩展属性='Excel 12.0 Xml;HDR=YES'
存储过程名称:usp_GetAllResultsData
选项卡结果预计有 4,165 行
选项卡结果收到 4,165 行
临时文件:C:\Webs\web-n-rsgpsd\Administration\ExtractOutput\DataExtractTemplate.xlsx
缓冲区长度:36,934 字节
很明显,下载的文件只有 37kb,但为什么查询的数据下载了 4k 行,但数据没有传递到相关工作表中?

© www.soinside.com 2019 - 2024. All rights reserved.