Picacodigos
« Diseño, Personas, y otras cosas
|
Mas Reciente
|
Menos reuniones... »
Guardar ficheros binarios en SQL Server
Published 150 weeks, 1 day ago
Mon
Feb
20
2006
En mi proyecto actual, una aplicación ASP .NET, el cliente expresó el deseo de guardar en base de datos las cartas, basadas en plantillas Word y generadas mediante la aplicación. Quieren guardarlas en la base de datos porque, al ser documentos oficiales, tienen que poder volver a imprimirse o visualizarse
exactamente igual
a como se crearon en su día. Por lo tanto, necesitamos un método para guardar los ficheros Word en la base de datos en formato binario, como
stream
de datos y ser capaces de poder recuperarlos después para su visualización.
Nota: no es el objetivo de este post la creación de ficheros Word desde código C#. Podéis usar para ello la automatización Word, o componentes de terceros como los publicados por
Aspose
, que son excelentes.
Vamos a crear una tabla simple en SQL Server para alojar los documentos. Para este ejemplo, la llamaremos
DocsBinarios
, y tendrá la siguiente estructura:
Campo
Tipo
Nulos?
DocId
Int (identity)
No
Documento
Image
No
NombreDoc
VarChar(100)
No
Es bastante autoexplicativo: el campo
DocId
es un campo de clave primaria autogenerado. El campo
Documento
es el que va a almacenar los streams de bits, es decir los propios ficheros Word en formato binario. El campo
NombreDoc
almacenará el nombre que se proporcionó originalmente al documento cuando se generó.
Después crearemos un procedimiento almacenado,
UploadDocs
, que servirá para guardar registros en esta tabla:
CREATE PROCEDURE
UploadDoc(@doc
AS
Image, @nombre
AS VarChar
(
100
))
AS
INSERT INTO
DocsBinarios (Documento, NombreDoc)
values
(@doc, @nombre)
GO
Colorized by:
CarlosAg.CodeColorizer
También es bastante autoexplicativo: un simple INSERT INTO que recibe como parámetros un
Image
y un
VarChar
Y éste es el método que guarda los datos en la base de datos:
private void
GuardarFicheroBDD(
string
sRuta,
string
sFichero)
{
//Creamos un nuevo objeto de tipo FileStream para leer el fichero
//Word en modo binario
System.IO.FileStream fs
= new
FileStream(sRuta + sFichero,
System.IO.FileMode.Open)
;
//Creamos un array de bytes para almacenar los datos leídos por fs.
Byte[] data
= new byte
[fs.Length]
;
//Y guardamos los datos en el array data
fs.Read(data,
0
, Convert.ToInt32(fs.Length))
;
//Abrimos una conexion. En este caso los datos de la cadena de
//conexion a la base de datos se recuperan de una sección del
//fichero web.config mediante ConfigurationSettings
SqlConnection cnn
=
new
SqlConnection(ConfigurationSettings.AppSettings[
"conexionBD"
])
;
cnn.Open()
;
//Creamos un comando de tipo StoredProcedure para invocar a
//UploadDocs
SqlCommand cmd
= new
SqlCommand(
"UploadDoc"
, cnn)
;
cmd.CommandType
=
CommandType.StoredProcedure
;
//Añadimos los parametros esperados y los valores de los mismos
cmd.Parameters.Add(
"@doc"
, data)
;
//los datos del fichero Word
cmd.Parameters.Add(
"@nombre"
, sFichero)
;
//y su nombre
//Ejecutamos el procedimiento almacenado, que inserta un nuevo
//registro en DocsBinarios con los datos que queremos introducir
cmd.ExecuteNonQuery()
;
//Cerramos la conexión y el fichero
cnn.Close()
;
fs.Close()
;
}
Colorized by:
CarlosAg.CodeColorizer
Ahora veamos el método para recuperar esos datos de la base de datos y mostrarlos como un fichero Word:
private void
LeerDeBD()
{
//Abrimos la conexion, exactamente igual que antes
SqlConnection cnn
=
new
SqlConnection(ConfigurationSettings.AppSettings[
"conexionBD"
])
;
cnn.Open()
;
//Este es el comando que abre el registro que deseamos. Para este
//ejemplo abrimos siempre el primer registro, habría que modificar
// este código para que el método recibiera como parámetro el
//registro que queremos abrir, claro.
SqlCommand comm
= new
SqlCommand(
"SELECT * FROM DocsBinarios " +
" WHERE docId = 1"
, cnn)
;
comm.CommandType
=
CommandType.Text
;
SqlDataAdapter da
= new
SqlDataAdapter(comm)
;
DataSet ds
= new
DataSet(
"Binarios"
)
;
da.Fill(ds)
;
//Creamos un array de bytes que contiene los bytes almacenados
//en el campo Documento de la tabla
byte
[] bits
=
((
byte
[])(ds.Tables[
0
].Rows[
0
].ItemArray[
1
]))
;
cnn.Close()
;
//Vamos a guardar ese array de bytes como un fichero en el
//disco duro, un fichero temporal que después se podrá descartar.
//Para evitar problemas de concurrencia de usuarios,
//generamos un nombre único para el mismo
string
sFile
=
"tmp"
+ GenerarNombreFichero() +
".doc"
;
//Creamos un nuevo FileStream, que esta vez servirá para
//crear un fichero con el nombre especificado
FileStream fs
= new
FileStream(Server.MapPath(
"."
) +
@"\DocsGenerados\"
+ sFile, FileMode.Create)
;
//Y escribimos en disco el array de bytes que conforman
//el fichero Word
fs.Write(bits,
0
, Convert.ToInt32(bits.Length))
;
fs.Close()
;
//Para mostrar el fichero, utilizamos una función
//JavaScript llamada mostrarFichero (que lo único que
//hace es cargar el fichero especificado)
//y hacemos que se ejecute en un pop-up.
string
script
=
"<script languaje='javascript'> "
;
script +
=
"mostrarFichero('DocsGenerados/"
+ sFile +
"') "
;
script +
=
"</script>"
+ Environment.NewLine
;
Page.RegisterStartupScript(
"mostrarFichero"
,script)
;
}
Colorized by:
CarlosAg.CodeColorizer
Y listo. Mediante éste último método el fichero Word se carga desde la base de datos y se muestra en un popup y en todo su esplendor.
Para que tengáis el código completo, ésta es la función JavaScript que carga el fichero generado desde base de datos:
<script language
=
"javascript"
>
function
mostrarFichero(destino) {
window
.open(destino,
null
,
"directories=no,height=600,
width=800,left=0,top=0,location=no,menubar=yes,
status=no,toolbar=yes,resizable=yes"
)
document
.forms(
0
).submit()
;
}
</script>
Colorized by:
CarlosAg.CodeColorizer
Y éste el método
GenerarNombreFichero()
, que utiliza la cuenta de
ticks
del servidor para crear nombres
cuasi
únicos de fichero.
private string
GenerarNombreFichero()
{
int
ultimoTick
=
0
;
while
(ultimoTick
==
Environment.TickCount)
{
System.Threading.Thread.Sleep(
1
)
;
}
ultimoTick
=
Environment.TickCount
;
return
DateTime.Now.ToString(
"yyyyMMddhhmmss"
) +
"."
+
ultimoTick.ToString()
;
}
Colorized by:
CarlosAg.CodeColorizer
Categorías:
.NET
|
Artículos
|
Comments [4]
Wednesday, March 22, 2006 5:40:16 PM (Romance Standard Time, UTC+01:00)
Hola
muy bueno lo que acabo de leer, justo ahora necesito almacenar diferentes tipos de archivos en una base de datos SQL, desde Visual Basic.
Me pregunto si me podrias ayudar, ya que no se si son los mismos tipos de datos en C y en Visual. Lo del array de bytes no me quedo muy claro, si me pudieras ayudar por favor.
Muchas Gracias.
Atte.
Orlando Bustos
Orlando Bustos M
Wednesday, March 22, 2006 9:29:09 PM (Romance Standard Time, UTC+01:00)
¿Te refieres a Visual Basic .NET? En ese caso creo que los tipos de datos son los mismos, aunque lógicamente la forma de declarar variables y arrays es distinta. Por ejemplo, donde en C# dice
Byte[] data = new byte[fs.Length];
en VB.NET creo que es
Dim data as new Byte[fs.Length]
De todas maneras, en la Red hay un buen montón de ejemplos para "traducir" de un lengujae a otro. Por ejemplo, este: http://www.4guysfromrolla.com/webtech/012702-1.shtml
Picacodigos
Wednesday, April 19, 2006 6:21:09 PM (Romance Daylight Time, UTC+02:00)
Pues he probado este ejemplo y me funciona bastante bien, lo he pasado a vs2005 y cambian algunas cosas claro, pero el problema q tengo es q el pop up se levannta pero se cierra inmediantamente. En local funciona perfectamente.
gracias por tu ayuda.
javier
Wednesday, October 04, 2006 11:29:07 AM (Romance Daylight Time, UTC+02:00)
Hola, el articulo es muy interesante, me pregunto si sabrías como hacer para una vez agregado el Documento a un Datatable (el idDoc, el Documento y el nombre), guardarlo desde ahi en la base de datos.
Saludos
Xavi
Comments are closed.
Buscar
Estadísticas
Total Posts: 112
This Year: 0
This Month: 0
This Week: 0
Comments: 328
Comentarios Recientes
RE: Microsoft Techdays y...
by Erick Alejan...
RE: Microsoft Techdays y...
by Venkman
RE: Microsoft Techdays y...
by Jesús
RE: Microsoft Techdays y...
by espinete
RE: Microsoft Techdays y...
by Pavleras
Software
Peeker
Acerca de...
Curriculum
Resume
Suscripcion
Suscribirse por correo
Categorias
.NET
Artículos
Blog
Eventos
Gadgets
Hardware
Herramientas
Opinión
Personal
ReSharper
Trucos
Ubuntu
Web
Archivo
January, 2008 (3)
December, 2007 (7)
November, 2007 (13)
October, 2007 (6)
September, 2007 (10)
August, 2007 (1)
July, 2007 (2)
June, 2007 (4)
May, 2007 (3)
March, 2007 (3)
February, 2007 (5)
January, 2007 (5)
December, 2006 (3)
November, 2006 (5)
September, 2006 (2)
August, 2006 (4)
July, 2006 (7)
June, 2006 (3)
May, 2006 (4)
April, 2006 (5)
March, 2006 (5)
February, 2006 (4)
January, 2006 (3)
Los blogs que leo
.Avery Blog
47 hats
Coding Horror
El lado del mal
Haacked
Jon Galloway
NET slave
Rob Conery
secretGeek
The daily WTF
The old new thing
Thinking in .NET
Velocidad de Escape
Contacto
Microblogging
Login
Sign In
Herramientas
Addicted to
The best C# & VB.NET refactoring plugin for Visual Studio 2005
Powered by
newtelligence dasBlog 1.9.7174.0
Tema basado en
Dandelion
, de Tim Sherrill