发信人: nightcat()
整理人: (1999-07-22 12:14:07), 站内信件
|
Jul-02-1999
Downloading and Uploading BLOBs from a SQL Database Using a
Browser
Part I of II
By Pieter Reint Siegers Kort
SQL Server has two data types that can be used to manipulate
large amounts of data - the text and image field data types.
The former is used to store large text objects, and the latter
Binary Large OBjects ( BLOB s) - although somewhat confusingly
the term 'object' in the context of SQL has nothing to do with
object orientated programming. The manner in which SQL works
with binary data types means that it's possible to use any sort
of binary stored file - JPG images, Word documents, PDF files,
and so on.
BLOBs used to be pretty tricky to work with in web development,
largely because of their structure and disk storage (physically
they are pointer-concatenated byte blocks). The introduction of
ASP/ADO (and in the example I will be looking at, some ActiveX
technology) has made it rather easier to up- and down - load
BLOBs (where 'upload' denotes the transfer of binary files from
the client browser to the SQL database and download the transfer
back again.) As you抣l see in the follow up article, on Monday,
it takes little more than a few minor code modifications to
prepare the data to be uploaded to the database.
To make use of the code we'll be looking at in this article
you're going to need:
Internet Explorer 4.01 with sp2
Visual Basic 6.0 with sp2
Visual InterDev 6.0 with sp2
ADO 2.0 with sp2 (comes with MDAC 2.0 with sp2)
on the client
NT4 preferably with sp5 (sp4 will do also)
Internet Explorer 4.01 with sp2
IIS 4.0 and ADO 2.0 with sp2
on the Web server and
SQL Server 6.5 with sp5a
on the SQL server.
You'll also need some knowledge about the creation of ActiveX
components in VB5 or VB6 - if you need help with this, or any
other programming language or technology covered in this
article, there are links to various help pages and tutorials
at the end.
The Scenario
Suppose there are some images that you want others to annotate
for you, on their machines, in their various locations, and to
save in a SQL server database table afterwards. Let's say that,
for the sake of the applications performance, the images for
download are small JPG previews of the originals, and have a
size of approximately 20-30 KB. The annotated images, together
with the related data, will be used at a later date to process
changes in the original image, and this will take place in
another department in another location. Because your users work
in different offices around the world, your application should
install, update, and register its components automatically
without their intervention. (They have, of course, installed
Internet Explorer 4.01 sp1/sp2, which is required for your
application to run smoothly, and have made the appropriate
alterations to their browser preferences.)
In this particular circumstance, you could develop an Intranet
with direct access, and the appropriate file permissions
assigned, to both the Web and SQL servers, which would make use
of a client component so that the annotations can be made
remotely. (Had the browser simply needed to display the images,
it would be is better to use a COM component on the Web server.)
In order to download the images from the SQL database, and
display it on the client抯 browser for further working, you can
use a custom COM ActiveX Control developed with VB6. This uses
ActiveX Data Objects (ADO) to access the database, retrieve the
requested image and save it on the local disk. If you are
familiar with components, you know that they have properties
and methods. Properties are like variables, and methods are
similar to VB public subs or functions, in that they perform
actions - database access, copying files, converting data, etc.
The Public properties and methods of a component can be
programmed from the outside world (i.e. accessed by another
component, a Web page, for example). You can make the component
methods and/or properties public by using VB ActiveX Control
Interface Wizard, or through your own methods and properties.
A component can also have private properties and methods, which
are used internally by the usercontrol or the embedded (intrinsic)
controls.
An Approach
Let's suppose that after the component has been developed,
tested, and compiled, it is called FotoEd6ocx. Among other
properties and methods, it has a public method which is called
LoadImage2(). This makes use of two ADO objects: the Connection
and Recordset objects, of which the Connection object, logically
enough, is used to connect to the database server, and the
Recordset object to receive and manipulate the query data. Let
have a closer look at what this method does for us:
Initially the ADO Connection and Recordset objects are named as
variants. These will be used later for the connection to the
database and retrieval of the image:
Dim con As New ADODB.Connection
Dim rs As New ADODB.Recordset
Then the connection string is created, which is used by the
component instead of a custom Data Source Name (DSN). DSNs are
used to define connections to a database server or file. Not
using them means eliminating the need to create a DSN on every
client machine but still requires that the core of ADO be
installed on it:
con.ConnectionString = "driver={SQL Server};" & _
"server=" & strServerSQL & ";uid=sa;pwd=;database=pubs"
con.ConnectionTimeout = 60
con.Open
Finally the SQL Stored Procedure (more of this later) is
executed, which is responsible for the retrieval of the image
bytes from the database:
if strServerSQL = strServerSQLRem then
strQuery = "GetPreview " & strPub_Id$
else
strQuery = strServerSQLRem & ".pubs..GetPreview " & strPub_Id$
end if
This also works on remote SQL servers, so long as the remote SQL
servers are registered as remote servers on the calling SQL
server, and vice versa. (You should do this for every connected
SQL server.) This is the dialog box of the submenu Remote
Servers from the menu Server in the SQL program Enterprise
Manager:
To add a Remote Server, type in the server name and in the
section Remote Logins, check Translate all Remote Login Names
to and choose the appropriate login (for example, a? checking
Trusted. Then click Add, repeat the steps for all other SQL
servers and close the window. Repeat the procedure on each SQL
server.
The SQL Stored Procedure (which is a compiled query) used to
retrieve the image bytes is quite simple:
CREATE Procedure GetPreview
@strPub_Id int
AS
set nocount on
/* maximum amount of bytes returned is 32KB */
set textsize 32768
select Preview=Logo
from Pub_Info
where pub_id=@strPub_Id
return
The table used here is an existing table from the pubs database
(Pub_Info). The line set textsize 32768 is added to increase
the amount of bytes returned by the query (the default size is
4 KB) when executed remotely.
This is the code fragment that saves the bytes on the local disk:
lngPictSize = rs(0).ActualSize
FileNum = FreeFile
Open FileName For Binary Access Write Lock Write As FileNum
Do While lngOffset < lngPictSize
varChunk = rs(0).GetChunk(conChunkSize)
Put #1, , varChunk
lngOffset = lngOffset + conChunkSize
If lngOffset > lngPictSize Then Exit Do
Loop
Close FileNum
The methods ActualSize and GetChunk determine the image size
and pass the bytes to the byte array (VarChunk) respectively.
The method GetChunk uses 32 KB chunks. The download at the end
of the article shows how the complete code for the LoadImage2()
method of the component fits together.
The next thing to do is to prepare the component for download
from the server. First you need to reference the VB project to
the ADO library (Microsoft ActiveX Data Objects 2.0 Library.)
Then compile the control, quit VB, and use VB6 Package &
Deployment Wizard to create an Internet Package and include all
the nesessary OCXs and DLLs, and associated dependencies. Be
sure to add the core ADO file Msado15.dll. You should also
include the VB run-time components. The wizard should produce
a document containing important guidelines for testing your
control.
The created Internet Package consists of a CABinet (CAB) file
and a sample HTML file. The CAB file is placed on the Web server
in a virtual directory, which allows virtual addressing to the
CAB file. In this way, the path specified in the codebase
property of the <OBJECT> tag (see the explanation of this tag
properties later in this article) is relative to the Intranet
and not to the specific machine, which makes it unnecessary to
change the path when the Intranet is copied. To protect your
files you can assign Read permission on the files (provided
your server uses Windows NT NTFS file system). If you want
maximum security, then it is better to place the CAB in a normal
but protected folder, but then the path of the codebase property
is an absolute path.
When users request a Web page containing the control definition,
their machine is checked for an installation of the CAB
components. If there isn't one, or the components are outdated,
the missing or updated files are downloaded, installed and
automatically registered: if everything is already on the
client then the local loads instantly.
So now your all set to integrate the component in a Web page.
Visual InterDev 6, which is part of MS Visual Studio 6, is
great for this, but if you want simplicity you can always use
Notepad. After we have created a workspace and a project we
will add an ASP page which has also a VBScript function (running
on the client-side) which will communicate with the component.
This code excerpt is from the sample HTML Web page containing
the <OBJECT> tag declaration:
<OBJECT classid="CLSID:416B1AD0-A61F-11D2-BCCD-00A0246D10AE"
codeBase=FotoEditor6ocx.CAB#version=6,0,0,3
id=FotoEd6ocx style="LEFT: 0px; TOP: 0px">
<PARAM NAME="_ExtentX" VALUE="13732">
<PARAM NAME="_ExtentY" VALUE="15478">
</OBJECT>
The <OBJECT> tag contains the declaration of the component. The
parameter ?CODE >classid?identifies a Global Unique IDentifier
(GUID.) GUIDs are used to uniquely identify your component, so
that it can be re-used by another computer without generating
run-time errors. GUIDs are generated based on the network card
ID of the computer from which it is compiled.
Another important parameter is the codebase, which points to a
relative directory on the Web server (in this case, the CAB file
is placed in the same directory as the Web pages). From this
directory the CAB components are downloaded when the client
requests the page. The attribute version checks the component
version on the client machine. The id parameter contains the
name of the component and is used when referring to the
component抯 methods and properties.
The component can be placed in your page using, for example, a
<TABLE> tag. This is the code segment of the ASP page which
calls the component抯 methods/properties:
<SCRIPT LANGUAGE="VBScript">
' init vars (code within ?lt;%= %>?is ASP code and runs on the ser ver)
strPub_Id = "<%= Trim(Request.QueryString("Pub_Id")) %>"
strServerSQL = "<%= Trim(Request.QueryString("ServerSQL")) %>"
strServerSQLRem = "<%= Trim(Request.QueryString("ServerSQLRem") ) %>"
' load the image
call FotoEd6ocx.LoadImage2(strPub_Id,strServerSQL,strServerSQLR em)
' visualize the window if it is hidden
Parent.focus()
</SCRIPT>
Note the call to the method LoadImage2() of the component.
Client-side VBScript is used to fill in the method parameters
and invoke the method. Only the parameter data is passed to the
component, and so the component takes care of the connection
and retreival of the image. Client-side VBScript is being used,
but as your target browser is IE, you could choose to use
client-side J(ava)Script, although the way methods and
properties are called in J(ava)Script is different and you would
need to translate the script shown here. I prefer VBScript
because the structure is narrowly related to VB, and I find
JavaScript is better suited to managing windows and frames, and
programming properties of HTML objects.
The last line - Parent.focus() - is a little trick I use which
allows the window re-appear when hidden on the screen. Using
the statement causes the window to pop-up after refreshing its
contents.
An afterthought
Although I'll draw more comprehensive conclusions at the end
of Monday's Part II, after I've shown you a method of uploading
BLOBs to SQL server, it seems appropriate at this point to draw
attention to the possibility of allowing users to access the Web
server anonymously. If they're mapped to a local Windows NT
account, having execute permission on SQL Stored Procedures only,
then your SQL database is better protected. You could also
implement a dedicated Proxy Server (otherwise known as a
firewall) as a gateway to the Internet, which can restrict
access to your pages and databases to specific sites.
-- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.124.22]
|
|