C# 将XLS转换为PDF:Getting";数据索引必须是字段“中的有效索引”;GetBytes()期间发生异常

C# 将XLS转换为PDF:Getting";数据索引必须是字段“中的有效索引”;GetBytes()期间发生异常,c#,mysql,filestream,binarywriter,mysqldatareader,C#,Mysql,Filestream,Binarywriter,Mysqldatareader,我有一个将文件转换为PDF的应用程序。它首先将MySQL中的一个blob保存到一个临时文件中,然后将该临时文件转换为PDF。只有在我尝试转换XLS文件时,GetBytes()才会出现“数据索引必须是字段中的有效索引”异常错误。其他文件类型(BMP、XLSX、DOC、DOCX等)都可以转换 private WriteBlobToTempFileResult WriteBlobToTempFile(int id, string fileType) { Logger.Log(string.Fo

我有一个将文件转换为PDF的应用程序。它首先将MySQL中的一个blob保存到一个临时文件中,然后将该临时文件转换为PDF。只有在我尝试转换XLS文件时,GetBytes()才会出现“数据索引必须是字段中的有效索引”异常错误。其他文件类型(BMP、XLSX、DOC、DOCX等)都可以转换

private WriteBlobToTempFileResult WriteBlobToTempFile(int id, string fileType)
{
    Logger.Log(string.Format("Inside WriteBlobToTempFile() id: {0} fileType: {1}", id, fileType));
    WriteBlobToTempFileResult res = new WriteBlobToTempFileResult //return object
    {
        PrimaryKey = id
    }; 
    FileStream fs;                          // Writes the BLOB to a file 
    BinaryWriter bw;                        // Streams the BLOB to the FileStream object.
    int bufferSize = 100;                   // Size of the BLOB buffer.
    byte[] outbyte = new byte[bufferSize];  // The BLOB byte[] buffer to be filled by GetBytes.
    long retval;                            // The bytes returned from GetBytes.
    long startIndex = 0;                    // The starting position in the BLOB output.                        
    string connectionString = ConfigurationManager.AppSettings["MySQLConnectionString"]; //connection string from app.config
    string path = ConfigurationManager.AppSettings["fileDirectory"]; //get directory from App.Config
    
    try
    {
        MySqlConnection conn = new MySqlConnection(connectionString);
        conn.Open();
        //Determine records to convert, retrieve Primary Key and file type
        string sql = "SELECT FILE_DATA from " + TableName + " WHERE PK_TSP_DOCS_ID = @id";
        MySqlCommand cmd = new MySqlCommand(sql, conn);
        cmd.Parameters.AddWithValue("@id", id);
        MySqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);                                                
        while (rdr.Read())
        {   
            // Create a file to hold the output.
            fs = new FileStream(path + @"\" + id + "." + fileType, FileMode.OpenOrCreate, FileAccess.Write);
            bw = new BinaryWriter(fs);

            // Reset the starting byte for the new BLOB.
            startIndex = 0;

            // Read the bytes into outbyte[] and retain the number of bytes returned.
            retval = rdr.GetBytes(rdr.GetOrdinal("FILE_DATA"), startIndex, outbyte, 0, bufferSize);

            // Continue reading and writing while there are bytes beyond the size of the buffer.
            while (retval == bufferSize)
            {
                bw.Write(outbyte);
                bw.Flush();

                // Reposition the start index to the end of the last buffer and fill the buffer.
                startIndex += bufferSize;
                // *****IT FAILS AT THE LINE BELOW*****
                retval = rdr.GetBytes(rdr.GetOrdinal("FILE_DATA"), startIndex, outbyte, 0, bufferSize);
                // *****IT FAILS AT THE LINE ABOVE*****
            }
            // Write the remaining buffer.
            bw.Write(outbyte, 0, (int)retval);
            bw.Flush();

            // Close the output file.
            bw.Close();
            fs.Close();
        }
        // Close the reader and the connection.
        rdr.Close();
        conn.Close();
        res.FullPath = path + @"\" + id + "." + fileType;
    }
    catch (Exception ex)
    {
        res.Error = true;
        res.ErrorMessage = string.Format("Failed to write temporary file for record id: {0} of file type: {1}", id.ToString(), fileType);
        res.InternalErrorMessage = ex.Message; //string.Format("Caught Exception in WriteBlobToTempPDF(). Stack Trace: {0}", ex.StackTrace);
    }                                    
    return res;
}

这是Oracle MySQL Connector/NET中的一个错误。您可以在MySql上看到,当试图读取缓冲区末尾的0字节时,Data会抛出一个
IndexOutOfRangeException
,但其他ADO.NET提供程序不会这样做

您应该切换到(免责声明:我是参与者)并使用
MySqlDataReader.GetStream()
和方法简化代码:

MySqlDataReader rdr=cmd.ExecuteReader(CommandBehavior.SequentialAccess); while(rdr.Read()) { //创建一个文件来保存输出。 使用(var fs=new FileStream(路径+@“\”+id+”+fileType,FileMode.OpenOrCreate,FileAccess.Write)) { //从数据读取器打开一个流 使用(var stream=rdr.GetStream(rdr.GetOrdinal(“文件\数据”)) { //复制数据 stream.CopyTo(fs); } } }
我只是想知道问题是否在于
Lenght==N*bufferSize
…然后
N*bufferSize
开始索引无效…使用
var length=rdr.GetBytes(索引,0,null,0,0)
获取长度…然后添加
startIndex
在非主题注释中:缓冲区大小应该更大…使用4KB,因为100B确实很小。将缓冲区大小从100更改为4000完成了此操作。不…这还不够…现在,当
文件长度%4000==0时,您将遇到问题。
使用第二条注释中的代码…做吗我仍然需要添加上面的代码?是的
var-length…
before
while
…并将while更改为
while(retval==bufferSize&&startIndex
我不确定..但我认为即使
while(startIndex
也应该这样做…是的,你也可以添加
var-index=rdr.GetOrdinal(“文件数据”);
并使用它多次调用
rdr.GetOrdinal(“文件数据”)