Hola:
Tengo una aplicación web (ASP) en la que los usuarios pueden adjuntar y visualizar todo tipo de documentos (pdf, tiff, jpeg, doc, xls…). Estos documentos se almacenan en una tabla de SQL Server 2005, utilizando un campo de tipo “image”.
Para almacenar los documentos, utilizo el archivo Loader.asp, que circula por internet:
<%
' -- Loader.asp --
' -- version 1.5
' -- last updated 6/13/2002
Class Loader
Private dict
Private Sub Class_Initialize
Set dict = Server.CreateObject("Scripting.Dictionary")
End Sub
Private Sub Class_Terminate
If IsObject(intDict) Then
intDict.RemoveAll
Set intDict = Nothing
End If
If IsObject(dict) Then
dict.RemoveAll
Set dict = Nothing
End If
End Sub
Public Property Get Count
Count = dict.Count
End Property
Public Sub Initialize
If Request.TotalBytes > 0 Then
Dim binData
binData = Request.BinaryRead(Request.TotalBytes)
getData binData
End If
End Sub
Public Function getFileData(name)
If dict.Exists(name) Then
getFileData = dict(name).Item("Value")
Else
getFileData = ""
End If
End Function
Public Function getValue(name)
Dim gv
If dict.Exists(name) Then
gv = CStr(dict(name).Item("Value"))
gv = Left(gv,Len(gv)-2)
getValue = gv
Else
getValue = ""
End If
End Function
Public Function saveToFile(name, path)
If dict.Exists(name) Then
Dim temp
temp = dict(name).Item("Value")
Dim fso
Set fso = Server.CreateObject("Scripting.FileSystemObject")
Dim file
Set file = fso.CreateTextFile(path)
For tPoint = 1 to LenB(temp)
file.Write Chr(AscB(MidB(temp,tPoint,1)))
Next
file.Close
saveToFile = True
Else
saveToFile = False
End If
End Function
Public Function getFileName(name)
If dict.Exists(name) Then
Dim temp, tempPos
temp = dict(name).Item("FileName")
tempPos = 1 + InStrRev(temp, "\")
getFileName = Mid(temp, tempPos)
Else
getFileName = ""
End If
End Function
Public Function getFilePath(name)
If dict.Exists(name) Then
Dim temp, tempPos
temp = dict(name).Item("FileName")
tempPos = InStrRev(temp, "\")
getFilePath = Mid(temp, 1, tempPos)
Else
getFilePath = ""
End If
End Function
Public Function getFilePathComplete(name)
If dict.Exists(name) Then
getFilePathComplete = dict(name).Item("FileName")
Else
getFilePathComplete = ""
End If
End Function
Public Function getFileSize(name)
If dict.Exists(name) Then
getFileSize = LenB(dict(name).Item("Value"))
Else
getFileSize = 0
End If
End Function
Public Function getFileSizeTranslated(name)
If dict.Exists(name) Then
temp = 1 + LenB(dict(name).Item("Value"))
If Len(temp) <= 3 Then
getFileSizeTranslated = temp & " bytes"
ElseIf Len(temp) > 6 Then
temp = FormatNumber(((temp / 1024) / 1024), 2)
getFileSizeTranslated = temp & " megabytes"
Else
temp = FormatNumber((temp / 1024), 2)
getFileSizeTranslated = temp & " kilobytes"
End If
Else
getFileSizeTranslated = ""
End If
End Function
Public Function getContentType(name)
If dict.Exists(name) Then
getContentType = dict(name).Item("ContentType")
Else
getContentType = ""
End If
End Function
Private Sub getData(rawData)
Dim separator
separator = MidB(rawData, 1, InstrB(1, rawData, ChrB(13)) - 1)
Dim lenSeparator
lenSeparator = LenB(separator)
Dim currentPos
currentPos = 1
Dim inStrByte
inStrByte = 1
Dim value, mValue
Dim tempValue
tempValue = ""
While inStrByte > 0
inStrByte = InStrB(currentPos, rawData, separator)
mValue = inStrByte - currentPos
If mValue > 1 Then
value = MidB(rawData, currentPos, mValue)
Dim begPos, endPos, midValue, nValue
Dim intDict
Set intDict = Server.CreateObject("Scripting.Dictionary")
begPos = 1 + InStrB(1, value, ChrB(34))
endPos = InStrB(begPos + 1, value, ChrB(34))
nValue = endPos
Dim nameN
nameN = MidB(value, begPos, endPos - begPos)
Dim nameValue, isValid
isValid = True
If InStrB(1, value, stringToByte("Content-Type")) > 1 Then
begPos = 1 + InStrB(endPos + 1, value, ChrB(34))
endPos = InStrB(begPos + 1, value, ChrB(34))
If endPos = 0 Then
endPos = begPos + 1
isValid = False
End If
midValue = MidB(value, begPos, endPos - begPos)
intDict.Add "FileName", trim(byteToString(midValue))
begPos = 14 + InStrB(endPos + 1, value, stringToByte("Content-Type:"))
endPos = InStrB(begPos, value, ChrB(13))
midValue = MidB(value, begPos, endPos - begPos)
intDict.Add "ContentType", trim(byteToString(midValue))
begPos = endPos + 4
endPos = LenB(value)
nameValue = MidB(value, begPos, endPos - begPos)
Else
nameValue = trim(byteToString(MidB(value, nValue + 5)))
End If
If isValid = true Then
intDict.Add "Value", nameValue
intDict.Add "Name", nameN
dict.Add byteToString(nameN), intDict
End If
End If
currentPos = lenSeparator + inStrByte
Wend
End Sub
End Class
Private Function stringToByte(toConv)
Dim tempChar
For i = 1 to Len(toConv)
tempChar = Mid(toConv, i, 1)
stringToByte = stringToByte & chrB(AscB(tempChar))
Next
End Function
Private Function byteToString(toConv)
For i = 1 to LenB(toConv)
byteToString = byteToString & chr(AscB(MidB(toConv,i,1)))
Next
End Function
%>
Este archivo está incluido en la página de acción (<!--#include file="../../includes/Loader.asp"-->), en la que hago lo siguiente:
Dim load
Set load = new Loader
load.initialize
Obtengo la información que necesito para hacer la insert:
fileData = load.getFileData("file")
Nombre = LCase(load.getFileName("file"))
Tamano = load.getFileSize("file")
contentType = load.getContentType("file")
Descripcion = load.getValue("descripcion")
TipoDocumento = load.getValue("TipoDocumento")
Defino las variables de conexión, e inserto el registro:
rsInsert.Open NombreTabla, objetoConexion, 2, 2
rsInsert.AddNew
rsInsert("TipoDocumento") = TipoDocumento
rsInsert("Nombre") = Nombre
rsInsert("Tamaño") = Tamano
rsInsert("Descripcion") = Descripcion
rsInsert("Fichero").AppendChunk fileData
rsInsert("TipoDatos") = contentType
rsInsert.Update
rsInsert.Close
Para visualizar los documentos, tengo un asp que se carga en un iframe, recogiendo la información de SQL y haciendo solamente lo siguiente:
Response.addHeader "Content-Disposition","inline;filename=" & NombreFichero
Response.ContentType = TipoDatos
Response.BinaryWrite Fichero
Response.End
Esto ha estado funcionando durante varios años perfectamente para todo tipo de documentos.
Haciendo pruebas por tema de migración a Office 2010, estoy teniendo problemas con los documentos Word (docx) y Excel (xlsx). Los archivos se guardan aparentemente sin problemas en la base de datos (TipoDatos = “application/vnd.openxmlformats-officedocument.wordprocessingml.document” y “application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”), pero a la hora de visualizar los documentos tengo problemas.
Al intentar abrir el archivo docx, me sale una ventana para guardar el archivo (en lugar de mostrarlo directamente en el explorador como hace con el resto de documentos). Una vez descargado, al abrirlo desde el explorador de Windows, dice lo siguiente: “El archivo no se puede abrir porque hay problemas con el contenido. Detalles: El archivo está dañado y no se puede abrir”. Me ofrece la opción de recuperar el contenido y al final consigo ver el contenido del documento.
Con el archivo xlsx, también me pasa algo parecido, pero en lugar de darme la opción de guardarlo, me da la opción de recuperarlo, lo consigue y me lo muestra en la ventana correcta (internet explorer).
También he probado a meter los tipos MIME en el IIS, pero sigue sin funcionar.
El resto de documentos siguen funcionado correctamente.
Las pruebas las he realizado en Internet Explorer 8.
He leído algo sobre algún byte extra que puede estar guardándose en SQL, pero no se me ocurre una solución.
Perdón por la chapa, pero no me he querido dejar ningún detalle.
Espero que me podáis ayudar, porque empiezo a estar un poco desesperado.
Muchas gracias