SQL 2000 IMAGE Feld ungerade Bytezahl klappt nicht

11/03/2010 - 09:24 von Carsten Lahme | Report spam
Prolog:
ich habe diese Frage schon bei .de.sqlserver gestellt -leider ohne Antwort.
im .iis.asp scheint nichts mehr los zu sein, daher die Frage ins
.dotnet.asp.
Es geht mir hier nicht um die Evaluierung neuer Techniken, sondern ich
möchte das Problem verstehen.

Hallo zusammen.

Ich habe ein recht merkwürdiges Problem -zumindestens für mein Verstàndnis.
Also kurz mal den Ablauf:
Eine Datenbank unter MS SQL 2000 mit einem IIS6 ASP Frontend.
In dieser Datenbank gibt es eine Tabelle, welche Dokumente beinhalten soll.
Da ich anfànglich Probleme hatte, die Dateien in die Datenbank zu bekommen
und auch wieder zu lesen, habe ich mir ein Script gesucht, welches die
Dateien auf der Festplatte ablegt.
In der Tabelle wird dann nur die Information zu der Datei gespeichert.

Mittlerweile habe ich mich soweit bewegt, daß ich nun doch endlich die
Dateien in der Datenbank haben wollte, da die Trennung zwischen Dateien und
Datenbankdatei eine gewisse Replikationsproblematik beinhaltet.

Also wieder auf die Suche nach einem Script und fündig geworden.
Das Frontend wurde so umgestellt, daß per "appendChunk" die binàren Daten in
ein IMAGE-Feld geladen werden.
Mit einem zweiten Script habe ich die vorhandenen Dateien lokal auf dem
Server in die Datenbank gepumpt.
Auch der "Download" -das Anzeigen; der Dokumente funktioniert.

Dann kam es urplötzlich bei einer ZIP-Datei zu Fehlern.
Die Datei wird in die Datenbank geladen, aber beim Öffnen wird sie als
korrupt angezeigt.

Nach einigem Hin und Her wurde der Fehler auch bei Textdateien
nachvollziehbar.
Und zwar bei Dateien mit einer UNGERADEN Bytezahl wird das letzte Byte
"abgeschnitten".

Beim Troubleshooting der Scripte konnte ich feststellen, das beim Speichern
auf die Festplatte ALLE BYTES vorhanden sind.
Beim Laden der Datei von der Festplatte in die Datenbank werden ebenfalls
ALLE BYTES geschrieben.
Nur beim direkten Laden aus dem Uploadscript in die Datenbank, fehlt
plötzlich das letzte Byte.

Hat jemand eine Idee?

Die verwendete Routine ist
'***************************************
' File: Upload.asp
' Author: Jacob "Beezle" Gilley
' Email: avis7@airmail.net
' Date: 12/07/2000
' Comments: The code for the Upload, CByteString,
' CWideString subroutines was originally
' written by Philippe Collignon...or so
' he claims. Also, I am not responsible
' for any ill effects this script may
' cause and provide this script "AS IS".
' Enjoy!
'****************************************

Nàheres unter http://www.asp101.com/articles/jaco...upload.asp

Hier die beiden fraglichen Ausschnitte:
=extrahieren per BinaryRead= Public Default Sub Upload()
Dim biData, sInputName
Dim nPosBegin, nPosEnd, nPos, vDataBounds, nDataBoundPos
Dim nPosFile, nPosBound

biData = Request.BinaryRead(Request.TotalBytes)
nPosBegin = 1
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(13)))

If (nPosEnd-nPosBegin) <= 0 Then Exit Sub

vDataBounds = MidB(biData, nPosBegin, nPosEnd-nPosBegin)
nDataBoundPos = InstrB(1, biData, vDataBounds)

Do Until nDataBoundPos = InstrB(biData, vDataBounds & CByteString("--"))

nPos = InstrB(nDataBoundPos, biData, CByteString("Content-Disposition"))
nPos = InstrB(nPos, biData, CByteString("name="))
nPosBegin = nPos + 6
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(34)))
sInputName = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
nPosFile = InstrB(nDataBoundPos, biData, CByteString("filename="))
nPosBound = InstrB(nPosEnd, biData, vDataBounds)

If nPosFile <> 0 And nPosFile < nPosBound Then
Dim oUploadFile, sFileName
Set oUploadFile = New UploadedFile

nPosBegin = nPosFile + 10
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(34)))
sFileName = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
oUploadFile.FileName = Right(sFileName,
Len(sFileName)-InStrRev(sFileName, "\"))

nPos = InstrB(nPosEnd, biData, CByteString("Content-Type:"))
nPosBegin = nPos + 14
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(13)))

oUploadFile.ContentType = CWideString(MidB(biData, nPosBegin,
nPosEnd-nPosBegin))

nPosBegin = nPosEnd+4
nPosEnd = InstrB(nPosBegin, biData, vDataBounds) - 2
oUploadFile.FileData = MidB(biData, nPosBegin, nPosEnd-nPosBegin)

If oUploadFile.FileSize > 0 Then Files.Add LCase(sInputName),
oUploadFile
Else
nPos = InstrB(nPos, biData, CByteString(Chr(13)))
nPosBegin = nPos + 4
nPosEnd = InstrB(nPosBegin, biData, vDataBounds) - 2
If Not mcolFormElem.Exists(LCase(sInputName)) Then mcolFormElem.Add
LCase(sInputName), CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
End If

nDataBoundPos = InstrB(nDataBoundPos + LenB(vDataBounds), biData,
vDataBounds)
Loop
End Sub
==
Speichern der Datei auf HDD -alle Bytes vorhanden== Public Sub SaveToDisk(sPath)
Dim oFS, oFile
Dim nIndex

If sPath = "" Or FileName = "" Then Exit Sub
If Mid(sPath, Len(sPath)) <> "\" Then sPath = sPath & "\"

Set oFS = Server.CreateObject("Scripting.FileSystemObject")
If Not oFS.FolderExists(sPath) Then Exit Sub

Set oFile = oFS.CreateTextFile(sPath & FileName, True)

For nIndex = 1 to LenB(FileData)
oFile.Write Chr(AscB(MidB(FileData,nIndex,1)))
Next

oFile.Close
End Sub

Daten in die Datenbank -letztes Byte wird
"abgeschnitten"== Public Sub SaveToDatabase(ByRef oField)
If LenB(FileData) = 0 Then Exit Sub

If IsObject(oField) Then
oField.AppendChunk FileData
End If
End Sub
=
Datei von Festplatte in Datenbank -funktioniert
'this one is to upload the filebased attachments into the SDB
'filename is related to the ID of the SDBs Record.
'Created on 09.03.2010 by Carsten Lahme
'Beta status

'steps to perform

'1. read all files from a given directory
'2. start loop for each file
'3. check, if filename matches to an existing record
'4.1.1 open file for binary read and appendchunk to existing record
'4.1.2 rename file by extending with "upl_"
'4.2.1 rename files w/o record with extending by "err_"

'Start of work'1. read all files from a given directory

Dim Workpath 'full given local path
Workpath="[Path to files]"
set myfso = createObject("scripting.filesystemobject") 'create
filesystemaccess
Set folder = myfso.GetFolder(WorkPath) 'open folder
Set files = folder.Files 'read files into array
Set conn = CreateObject("ADODB.Connection") 'create a DB object
dbconnect="driver={sql server};server=[FQDN of
server];database=[databasename]"
conn.Open dbconnect 'open the SDB


'2. Start loop for each file
For each currentFile In files

'3. check, if filename matches to an existing record.
filename=currentFile.Name 'get filename
' wscript.echo "processing " & workpath & filename 'debug
FN_LEN=len(filename) 'get length of filename
fileID=cint(left(filename,FN_LEN-4)) 'cutoff the extension
mysql="select count(*) as rcount from changelogattachments where id=" &
fileID 'set SQL statement
set rs=conn.execute(mysql) 'load from SDB
if rs("rcount")<>1 then
'4.2.1 error: rename file
myfso.movefile workpath & filename, workpath & "err_" & filename
else
'record found
'4.1.1 open file for binary read and upload to record
filebindata=ReadBinaryFile(workpath & filename)
'in this case we need a Record Set to store binary data
Set rsconn = CreateObject("ADODB.Recordset")
'specifiy the connection
rsdbconnect="driver={sql server};server=[FQDN of
server];database=[databasename]"
'open Recordset on table
rsconn.open "select * from changelogattachments where id=" & fileID ,
rsdbconnect, 2,2
rsconn.movefirst 'select matching record
rsconn("attbindata").appendchunk null 'clear existing data
rsconn.update 'and update
rsconn("attbindata").appendchunk filebindata 'append filedata
rsconn("attContentType")="application/octet-stream"
rsconn.update 'and update
rsconn.close 'well... close the record
myfso.movefile workpath & filename, workpath & "upl_" & filename 'rename
file
end if
Next

conn.close 'close SDB connection
conn = nothing 'destroy database object
myfso=nothing 'destroy file system object
files = nothing 'destroy filelist

'this function gets the binary data from the file
Function ReadBinaryFile(FileName)
Const adTypeBinary = 1

'Create Stream object
Dim BinaryStream
Set BinaryStream = CreateObject("ADODB.Stream")

'Specify stream type - we want To get binary data.
BinaryStream.Type = adTypeBinary

'Open the stream
BinaryStream.Open

'Load the file data from disk To stream object
BinaryStream.LoadFromFile FileName

'Open the stream And get binary data from the object
ReadBinaryFile = BinaryStream.Read
End Function
=
 

Lesen sie die antworten

#1 Thomas Bandt
11/03/2010 - 14:03 | Warnen spam
Am 11.03.10 09:24, schrieb Carsten Lahme:
Hat jemand eine Idee?



Sorry, wenn das destruktiv klingt, aber: was machst
du da? SQL Server 2000? ASP? Warum arbeitest du mit
diesen làngst verstorbenen Technologien?

Und selbst wenn du das musst: ich halte absolut
nichts davon, Dateien binàr in einer Datenbank zu
speichern. Man kann hier viel diskutieren, ich
akzeptiere auch andere Ansichten, aber ich hatte
in knapp 10 Jahren noch keinen Fall, wo ich es
bereut hàtte, anders verfahren zu sein.

Für die Replizierung von Files im Filesystem gibt
es kleine, billige und zuverlàssige Tools (Second
Copy z.B.), das Synchronisieren mit den Referenzen
in der Datenbank ist nun auch kein großes Problem.

Gruß, Thomas [MVP ASP/ASP.NET]
http://www.69grad.de

Ähnliche fragen