2012-07-17 53 views
6

Tengo problemas para leer un blob de una base de datos MySQL. Lo he conseguido insertar con éxito en la base de datos, pero parece que no puedo leerlo. Sé que algunos de ustedes podrían estar pensando "¿por qué está usando una base de datos para almacenar blobs para imágenes, y no solo las rutas de archivos/nombres de archivos", pero quiero tener flexibilidad y muchas de estas imágenes se almacenarán en una servidor y no localmente, esto optimiza la eficiencia y me permite mover las imágenes a local si es necesario. He seguido un tutorial (breve) y he escrito este método para recibir un blob;leyendo la imagen BLOB de la base de datos MySQL

public void getBlob(string query, string fileOut) 
    { 
     if (this.OpenConnection() == true) 
     { 
      MySqlCommand cmd = new MySqlCommand(query, mConnection); 

      //the index number to write bytes to 
      long CurrentIndex = 0; 

      //the number of bytes to store in the array 
      int BufferSize = 100; 

      //The Number of bytes returned from GetBytes() method 
      long BytesReturned; 

      //A byte array to hold the buffer 
      byte[] Blob = new byte[BufferSize]; 


      //We set the CommandBehavior to SequentialAccess 
      //so we can use the SqlDataReader.GerBytes() method. 

      MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess); 

      while (reader.Read()) 
      { 
       FileStream fs = new FileStream(DeviceManager.picPath + "\\" + reader["siteBlobFileName"].ToString(), FileMode.OpenOrCreate, FileAccess.Write); 
       BinaryWriter writer = new BinaryWriter(fs); 
       CurrentIndex = 0; 
       BytesReturned = reader.GetBytes(1, CurrentIndex, Blob, 0,BufferSize); 

       while (BytesReturned == BufferSize) 
       { 
        writer.Write(Blob); 
        writer.Flush(); 
        CurrentIndex += BufferSize; 
        BytesReturned = reader.GetBytes(1, CurrentIndex, Blob, 0, BufferSize); 
       } 

       writer.Write(Blob, 0, (int)BytesReturned); 
       writer.Flush(); 
       writer.Close(); 
       fs.Close(); 
      } 
      reader.Close(); 

      this.CloseConnection(); 
     } 
    } 

y lo estoy llamando al igual que ..

mDBConnector.getBlob("SELECT siteMapPicture, siteBlobFilename FROM sites WHERE siteID = '" + DeviceManager.lastSite + "'", DeviceManager.picPath + "mappicsite" + DeviceManager.lastSite); 


PBSite.BackgroundImage = Image.FromFile(DeviceManager.picPath + "mappicsite" + DeviceManager.lastSite); 

Sin embargo, es erroring en los BytesReturned = reader.GetBytes (1, currentIndex, Blob, 0, BufferSize); con el error "GetBytes solo se puede invocar en columnas binarias o guid". Supongo que esto tiene que ver con mi tipo de campo en mi base de datos, pero cambiar la columna a tipo binario significa que tengo que almacenar eso como una especie de blob, pero quiero dejar el nombre del archivo como una cadena normal. ¿Se me escapa algo? u otra forma de hacer esto?

edit1: creo que el primer parámetro para bytesreturned es hacer con la columna en el lector, estableciendo esto en 0 da el error "Intento no válido de leer una columna anterior usando SequentialAccess", miro esto.

edit2: Eliminar el acceso secuencial me da un archivo de 13 bytes (que podría ser solo la primera fila, ¿por qué el acceso secuencial lee todas las filas?) Así que tal vez estoy leyendo columnas en el orden incorrecto.

edición 3: creo que la razón de este error se debe a la forma en que ingresé a la base de datos. habiendo cambiado este método, mi saveBlob ahora se ve así:

public void saveBlob(string filePath, string fileName, string siteID) 
    { 
     if (this.OpenConnection() == true) 
     { 

      //A stream of bytes that represnts the binary file 
      FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); 

      //The reader reads the binary data from the file stream 
      BinaryReader reader = new BinaryReader(fs); 

      //Bytes from the binary reader stored in BlobValue array 
      byte[] BlobValue = reader.ReadBytes((int)fs.Length); 

      fs.Close(); 
      reader.Close(); 


      MySqlCommand cmd = new MySqlCommand(); 
      cmd.Connection = mConnection; 
      cmd.CommandType = CommandType.Text; 
      cmd.CommandText = "INSERT INTO x (y, z) VALUES (@BlobFile, @BlobFileName)"; 

      MySqlParameter BlobFileNameParam = new MySqlParameter("@BlobFileName", SqlDbType.NChar); 
      MySqlParameter BlobFileParam = new MySqlParameter("@BlobFile", SqlDbType.Binary); 
      cmd.Parameters.Add(BlobFileNameParam); 
      cmd.Parameters.Add(BlobFileParam); 
      BlobFileNameParam.Value = fileName; 
      BlobFileParam.Value = BlobValue; 



       cmd.ExecuteNonQuery(); 

      this.CloseConnection(); 
     } 
    } 

que he corrió a través del depurador, y ambos blobvalue y blobfileparam (@blobfile) tienen el mismo tamaño (alrededor de 150 mil), pero está erroring al momento de celebrar la consulta, dando el siguiente error;

"unable to cast object of type 'system.byte[]' to type 'system.iconvertible" 

que he tomado una mirada hacia el código y trataron de cambiar los tipos binarios de imagen, para permitir que los archivos más grandes, pero da el mismo error. ¿Alguien sabe algo sobre esta nueva información?

editar 4: arreglado todo. di cuenta de que en mi código i estaba usando:

("@BlobFile", SqlDbType.Binary); 

cambian estos tipos de "MySqlDbType" (derp) y me permitió elegir los tipos de burbuja. Las cosas finalmente están funcionando como se esperaba:)

+1

No soy un experto en C#, pero que está seleccionando 2 columnas - '' y 'siteMapPicture siteBlobFilename' - son dos gotas o es una varchar/char/text? –

+0

siteMapPicture es un BLOB, siteBlobFilename es varchar –

+0

No es un desarrollador de C#, pero su campo blob no sería la columna # 0, mientras que está tratando de obtener bytes en la columna # 1, ¿cuál sería el campo de ruta? –

Respuesta

3

¿Ha intentado simplificar primero? En lugar de leer BLOB 100 bytes a la vez, intente simplificar su código para que solo lea todos los bytes en un archivo. De esta forma, puede descartar fácilmente los problemas de la capa de datos.

la siguiente documentación también sugiere vaya a guardar el tamaño de archivo como otra columna: http://dev.mysql.com/doc/refman/5.5/en/connector-net-programming-blob.html

Cuestiones relacionadas