PDF in SQL Server abspeichern und wieder abrufen

1082 Aufrufe
Direkt zur ersten ungelesenen Nachricht

Thomas Brausendorf

ungelesen,
28.05.2007, 08:42:0028.05.07
an
Hallo zusammen!

Ich habe ein Problem und zwar geht es darum ein oder mehrere PDF-Dokumente
als Binärstream aus der Datenbank zu lesen und wieder in eine Datei zu
schreiben.

Folgendes Szenario:

Eine Person hat immer eine PDF-Datei als Feld in der DB.
Das auswählen und speichern des PDF-Dokuments ist kein Problem über ein Byte()

Jetzt möchte ich eine Form erstellen mit einem Link für jede Person über die
sich diese PDF-Datei(als Binärdatei in der DB) einfach öffnen lässt.
(Process.Start("Dateipfad")

Meiner MEinung nach müsste ich die Binärdaten als Stream wieder zurück in
eine Datei schreiben und diese dann einfach öffnen.
Aber wie???

Ist das möglich oder habe ich da irgendwo einen Denkfehler drin?

Im vorhinein vielen Dank!!!

Lars Breiter

ungelesen,
29.05.2007, 10:57:0029.05.07
an
"Thomas Brausendorf" wrote:

Hallo Thomas,

hier mal ein kleines Codebeispiel, wie ich PDF's im SQL Server speichere.

\\\
Dim f As New IO.FileInfo(File)
Dim fs As IO.FileStream
Dim bNachrichtimage() As Byte

ReDim bNachrichtimage(f.Length - 1)
'Datei in den redimensionierten Byte-Array einlesen
fs = f.OpenRead
fs.Read(bNachrichtimage, 0, f.Length)
fs.Close()

QuerySQL = "INSERT INTO Nachricht (NachrichtID,@Nachrichtimage"
QuerySQL &= " VALUES (@NachrichtID,@NachrichtImage)"

Dim comSQL As New SqlClient.SqlCommand(QuerySQL, cnSQL)

comSQL.Parameters.Add(New SqlClient.SqlParameter("@NachrichtID",
SqlDbType.Int)).Value = sNachrichtId
comSQL.Parameters.Add(NewSqlClient.SqlParameter("@NachrichtImage",
SqlDbType.Image)).Value = bNachrichtimage

comSQL.ExecuteNonQuery()
///

Und das zurückgewinnen geht genau andersrum. Also zuerst binär auslesen
und in ein Filestream-Objekt zurückschreiben.

Viele Grüße
Lars Breiter

Thomas Brausendorf

ungelesen,
29.05.2007, 11:45:0129.05.07
an
Ja genau da ist mein Problem mit dem zurück gewinnen. Ich programmiere noch
nicht allzulang aber habe immer solche Brocken (für mich) zu bewältigen :-)

Hast Du da vielleicht noch ein Codebeispiel für das zurück gewinnen damit
ich die Systematik dahinter richtig verstehe? Das wäre echt nett :-)

Danke schon mal im Voraus!

Lars Breiter

ungelesen,
29.05.2007, 12:36:0129.05.07
an
Hallo Thomas,

die ein kleines Codebeispiel, wie Du das PDF wieder "zurückholst".

\\\
Dim Query as string
Dim Read as SQLClient.SQLDatareader
Dim arr() As Byte
Dim arrlength As Long

'in der Abfrage die Länge der Datei abfragen mit Funktion "Datalength"
'um zu wissen, wie groß die Datei werden soll
Query = "SELECT DATALENGTH(Nachrichtimage), NachrichtImage FROM Nachricht
WHERE Nachrichtid = " & id

Read = readSQL.SQLQuery(Query, SQLConnection)

While SQLVar.read1.Read
'Auslesen, wie groß die Datei werden muss...
arrlength = SQLVar.read1.GetValue(0)

'... anschließend das Array soweit vergrößern
ReDim arr(arrlength - 1)

SQLVar.read1.GetBytes(1, 0, arr, 0, arrlength)

'... einen neuen Filestream erzeugen
Dim f As New System.IO.FileStream(Application.StartupPath & "\temp.pdf",
IO.FileMode.Create, IO.FileAccess.ReadWrite, IO.FileShare.ReadWrite)

'... und diesen einfach Wegschreiben
f.Write(arr, 0, arrlength)
f.Close()
End While
///

Ich hoffe ich konnte Dir etwas helfen. Dieser Code ist jetzt etwas verkürzt,
da
ich selber nicht nur PDF's, sondern auch Textdatei und Bilder so abspeichere
und
vorher eine Auswahl treffen muss, um welchen Dateityp es sich handelt.

Viele Grüße
Lars Breiter

Thomas Brausendorf

ungelesen,
29.05.2007, 15:25:0329.05.07
an
Besten Dank!!!
Davon war ich noch Meilen entfernt :-)
Aber irgendwann komme ich bestimmt wieder wegen Bildern, Texten und anderen
Dateien!
Aber damit kann ich schon sehr viel anfangen.

Thomas Brausendorf

ungelesen,
01.06.2007, 15:27:0201.06.07
an
Ich habe den Code soweit probiert aber bekomme immer Ausnahmefehler wegen
fehlender Daten

Ich denke es hat mit dieser Zeile zu tun:

SQLVar.read1.GetBytes(1, 0, arr, 0, arrlength)

Was ist denn eigentlich SQLVar ? Ist leider im Beispiel nirgendwo deklariert..

Hier mal mein Code:
/////////
'Herstellen und öffnen einer Verbindung zu einem SQL-Server mittels ADO.NET
Dim con As SqlConnection = New SqlConnection("Data
Source=WS-TB\SQLEXPRESS;Initial Catalog=Adressen;Integrated Security=SSPI")
con.Open()


'Das command-Objekt (Absetzen von SQL-Statements)
Dim cmd As New SqlCommand
'Oder Dim cmd As New SqlCommand(cmdText, connection)
cmd.CommandText = "Select DATALENGTH(bild), bild from NameAnschrift
Where adresse_id = 7" 'Das SQL-Statement
cmd.Connection = con 'Verbindung des Command-Objekts

Dim read As SqlDataReader
read = cmd.ExecuteReader
Dim arrLength As Long

Dim arr() As Byte

While read.Read()
arrLength = read.GetValue(0)

End While

ReDim arr(arrLength - 1)
read.GetBytes(8, 0, arr, 0, arrLength)
con.Close()

'File schreiben
Dim writer As StreamWriter = New StreamWriter("c:\Testbild.jpg")
writer.Write(arr)
writer.Close()

////////////

Vielleicht kannst Du mir da nochmal weiterhelfen? Der Fehler wird durch
diese Zeile erzeugt:
read.GetBytes(8, 0, arr, 0, arrLength)

Elmar Boye

ungelesen,
02.06.2007, 08:15:2102.06.07
an
Hallo Thomas,
Thomas Brausendorf <ThomasBr...@discussions.microsoft.com> schrieb ...

> Ich habe den Code soweit probiert aber bekomme immer Ausnahmefehler wegen
> fehlender Daten
>
> Ich denke es hat mit dieser Zeile zu tun:
>
> SQLVar.read1.GetBytes(1, 0, arr, 0, arrlength)

Eher damit, dass Du bereits am Ende der Daten gelandet bist...

> Dim arr() As Byte
> While read.Read()
> arrLength = read.GetValue(0)
> End While
>
> ReDim arr(arrLength - 1)
> read.GetBytes(8, 0, arr, 0, arrLength)

Unten mal eine andere Fassung, die eine spezielle Version für
SQL Server 2005 und VARBINARY(MAX) anstatt IMAGE enthält.

Gruss
Elmar


#Region "Sql Server Read/Write Blob"
Private Const CONNECTION_STRING As String = "Data Source=(local)\SQL2005;Initial Catalog=tempdb;Integrated Security='true'"
Private Const BUFFER_SIZE As Integer = 65536

Public Sub SqlBlobCreateTable()
Using connection As New SqlConnection(CONNECTION_STRING)
connection.Open()

' SQL Sever 2005 mit varbinary(max) sonst image
Dim dataType As String = "image"
If (connection.ServerVersion.StartsWith("09")) Then
dataType = "varbinary(max)"
End If
Dim command As New SqlCommand( _
"IF OBJECT_ID(N'dbo.Blobs', 'U') IS NULL " & _
"CREATE TABLE [dbo].[Blobs]( " & _
" [Id] [int] IDENTITY(1,1) NOT NULL, " & _
" [Daten] " & dataType & " NULL, " & _
" CONSTRAINT [PK_Blobs] PRIMARY KEY CLUSTERED ([Id]) )", _
connection)
command.ExecuteNonQuery()
End Using
End Sub

Public Function SqlBlobWrite(ByVal fileName As String) As Integer
' Schreiben in einem Block - für grosse Datenblöcke nicht zu empfehlen
Using connection As New SqlConnection(CONNECTION_STRING)
connection.Open()

Dim dataBuffer() As Byte = System.IO.File.ReadAllBytes(fileName)

Dim command As New SqlCommand("INSERT INTO Blobs (Daten) VALUES (@DataBuffer); SELECT SCOPE_IDENTITY() AS Id",
connection)
command.Parameters.Add(New SqlParameter("@DataBuffer", SqlDbType.Image, dataBuffer.Length)).Value = dataBuffer
Return CType(command.ExecuteScalar(), Integer)
End Using
End Function

Public Function SqlBlobWrite2005(ByVal fileName As String) As Integer
' Nur für VARBINARY(max)
' Für speicherschonende SQL Server 2000 Version siehe: http://msdn2.microsoft.com/de-de/library/3517w44b(VS.80).aspx
Using connection As New SqlConnection(CONNECTION_STRING)
connection.Open()

Using streamInput As New FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, BUFFER_SIZE)
Dim dataID As Integer
Dim dataLength As Long
Dim dataBuffer(BUFFER_SIZE - 1) As Byte

dataLength = streamInput.Read(dataBuffer, 0, dataBuffer.Length)
If (dataLength > 0) Then
If (dataLength < BUFFER_SIZE) Then
Array.Resize(dataBuffer, CType(dataLength, Integer))
End If
Dim command As New SqlCommand("INSERT INTO dbo.Blobs (Daten) VALUES (@DataBuffer); SELECT SCOPE_IDENTITY() AS
Id", connection)
command.Parameters.Add(New SqlParameter("@DataBuffer", SqlDbType.VarBinary, BUFFER_SIZE)).Value = dataBuffer
dataID = CType(command.ExecuteScalar(), Integer)

command.CommandText = "UPDATE dbo.Blobs SET " & _
"Daten.Write(@DataBuffer, NULL, NULL) " & _
"WHERE ID = @ID;"

command.Parameters.Clear()
command.Parameters.Add(New SqlParameter("@ID", SqlDbType.Int)).Value = dataID
command.Parameters.Add(New SqlParameter("@DataBuffer", SqlDbType.VarBinary, BUFFER_SIZE))

dataLength = streamInput.Read(dataBuffer, 0, dataBuffer.Length)
Do While (dataLength > 0)
If (dataLength < BUFFER_SIZE) Then
Array.Resize(dataBuffer, CType(dataLength, Integer))
End If
command.Parameters("@DataBuffer").Value = dataBuffer
command.ExecuteNonQuery()

dataLength = streamInput.Read(dataBuffer, 0, dataBuffer.Length)
Loop

Return dataID
Else
Throw New IOException(String.Format("Die Eingabedatei '{0}' ist leer.", fileName))
End If
End Using
End Using
End Function


Public Sub SqlBlobRead(ByVal dataId As Integer, ByVal fileName As String)
' Einlesen via Puffer
Using connection As New SqlConnection(CONNECTION_STRING)
connection.Open()

Dim command As New SqlCommand("SELECT Daten FROM dbo.Blobs WHERE ID = @ID", connection)
command.Parameters.Add(New SqlParameter("@ID", SqlDbType.Int)).Value = dataId

Using reader As SqlDataReader = command.ExecuteReader(CommandBehavior.SequentialAccess)
Dim dataIndex As Long
Dim dataLength As Long
Dim dataBuffer(BUFFER_SIZE - 1) As Byte

If (reader.Read()) Then
Using streamOutput As New FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None, BUFFER_SIZE)
Do
dataLength = reader.GetBytes(0, dataIndex, dataBuffer, 0, BUFFER_SIZE)
If (dataLength > 0) Then
streamOutput.Write(dataBuffer, 0, CType(dataLength, Integer))
dataIndex += dataLength
End If
Loop While (dataLength > 0)
End Using
End If
End Using
End Using
End Sub

Private Sub TestSqlBlob()
Dim watch As New Stopwatch()
Dim dataId As Integer

SqlBlobCreateTable()

watch.Start()
'dataId = SqlBlobWrite("C:\Input.JPG")
dataId = SqlBlobWrite2005("C:\Input.JPG")
watch.Stop()
Console.WriteLine("SqlBlob Write: {0}", watch.ElapsedMilliseconds)

watch.Reset()
watch.Start()
SqlBlobRead(dataId, "C:\Output.JPG")
watch.Stop()
Console.WriteLine("SqlBlob Read: {0}", watch.ElapsedMilliseconds)

End Sub
#End Region ' "Sql Server Read/Write Blob"


Allen antworten
Dem Autor antworten
Weiterleiten
0 neue Nachrichten