Uploading and Downloading BLOBs
BLOBs are Binary Large Objects. A BLOB can be any random large block of bits such as a Word document, a picture, or sound file.
You can use HTML forms and special adapter webjects to upload BLOBs from a web browser to a database, and download BLOBs from a database to a web browser. The following sections discuss the use of form variables and provide examples for uploading and downloading BLOBs.
For additional information on the adapter webjects that upload and download BLOBs, see the appropriate adapter guide.
For advanced users, Info*Engine also provides methods such as setOutputStream, setInputStream, and sendContent that can manipulate BLOBs and the Java language provides classes such as java.io.ByteArrayInputStream and java.io.ByteArrayOutputStream to read or write BLOBs to or from memory.
|
The following examples include JDBC adapter webjects with SQL statements. These are simple examples, and do nothing to preprocess user-supplied input to protect database content from malicious users. Task authors should take precautions to validate user input to protect against malicious user attacks. Such attacks may attempt to exploit tasks using SQL injection or by supplying malformed parameter values, which can cause data corruption or allow access to protected data.
|
Using Form Variables When Uploading BLOBs
To upload BLOBs, the HTML form element on your JSP page must include the following attributes:
method="POST"
action="task_to_execute"
enctype="multipart/form-data"
These attributes establish the environment required for streaming the BLOB and storing the form variables.
To understand how to use form variables and how to control BLOB processing, it is helpful to know how the web browser, Info*Engine, adapter, and database interact to transfer BLOB data from the browser to a database. The following interactions identify the major steps that occur when a form is submitted from the browser:
• The browser sends the form variables and file data as a stream of data through the web server to the Info*Engine servlet.
• To maintain the optimum performance, the Info*Engine servlet and Info*Engine server process the stream as it is received rather than reading and storing the entire stream before doing anything.
• The servlet reads any form variables stored at the beginning of the input stream and stores them in the @FORM context group until the first BLOB data is encountered.
• When a BLOB is encountered, the Info*Engine servlet stops storing variables and passes the BLOB data on to its output stream so that the stream continues on to the Info*Engine server.
• By executing the task that is identified in the HTML form action attribute, the Info*Engine server connects to an adapter and passes the BLOB on to the adapter.
• By executing the webject in the task, the adapter then connects to a database and sends the BLOB to the database.
The following example code contains explanatory text and a form for selecting a file to store in the column of a database row. This example posts the data directly to an Info*Engine task using the Info*Engine servlet, meaning the client receives the XML output from task execution upon clicking “Submit”:
<%@page language="java" session="false" errorPage="../IEError.jsp"%>
<%@ taglib uri="http://www.ptc.com/infoengine/taglib/core" prefix="ie" %>
<html>
<head>
<title>Upload File</title>
</head>
<body>
This page prompts for a "name" and "file" to store in an database.
The "name" is used to select a row in the table. The value of
"name" and the "file" contents are stored in columns in the selected row.
The table must be created before this example is run. The table could be created
using a SQL statement like 'CREATE TABLE BLOBTEST (NAME VARCHAR(60),FILECONTENT BLOB)'
<h2>Upload File to Oracle BLOB Column</h2>
<form method="POST" action="/Windchill/servlet/IE/tasks/com/company/UploadBlob.xml"
enctype="multipart/form-data">
<TABLE>
<tr> <td align=right>
<B><FONT FACE=arial,helvetica>Adapter Instance:
</td>
<td>
<INPUT name = "instance" type="text" size=50>
</td>
</tr>
<tr> <td align=right>
<B><FONT FACE=arial,helvetica>Name:
</td>
<td>
<INPUT name = "filename" type="text" size=50>
</td>
</tr>
<tr> <td align=right>
<B><FONT FACE=arial,helvetica>File:
</td>
<td>
<INPUT name = "file" type="file" size=50>
</td>
</tr>
<tr> <td align=right>
<INPUT type=submit NAME="submit" VALUE="Submit" id=button>
</td>
</tr>
</TABLE>
</form></body></html>
The file select control displayed through the third form INPUT element provides the vehicle from which the user selects the file to upload and, when the data stream is created, the BLOB data in the file selected is streamed right after the form variables set from the first two INPUT elements.
The UploadBlob.xml task identified in the action attribute of the form element is the task that the Info*Engine server executes. This task (which is described in the next section) uses the form variables to identify the adapter instance and specify the name that corresponds to the BLOB in the table row where the BLOB is stored.
To ensure that Info*Engine stores the form variables for use in the task, the form variables must be set in INPUT elements that are before the INPUT element that selects the BLOB file (as is done the previous example). If the order of the INPUT elements was reversed in the previous example, the form variables required by the task would not be stored in the @FORM context group because they would not appear in the stream until after the BLOB data. Any form variables in the stream after a BLOB are lost because the server does not read the entire stream before transferring it on to the adapter. Instead, the server transfers the BLOB directly to the adapter without first buffering the entire thing in memory. This optimizes performance and allows very large files to be sent to adapters without requiring enormous amounts of system memory.
Controlling Which Webjects Get Uploaded BLOBs
When BLOBs are uploaded to Info*Engine from a web page or Info*Engine-based application, Info*Engine cannot determine which adapter webjects consume the BLOBs or how many BLOBs each webject should consume. By default, Info*Engine attempts to deliver all available BLOBs to the first adapter webject (any webject with a type of ACT or OBJ). Sometimes, the first adapter webject is not a webject that consumes BLOBs, so the default behavior of Info*Engine is not always appropriate.
To control how BLOBs are consumed by webjects, you can include the BLOB_COUNT parameter on any adapter webject. This parameter specifies how many BLOBs should be delivered to the adapter webject. You can specify a value of 0 when no BLOBs should be delivered to the webject. If you omit the BLOB_COUNT parameter, all remaining BLOBs are delivered to the webject.
The following UploadBlob.xml example task contains three adapter webjects. The first two webjects (Do-Sql) delete and add rows to a database table and do not use BLOBs. On these webjects, the BLOB_COUNT parameter is set to 0. The third webject (Put-Blob-Stream) is the webject that stores the BLOB and it has been defined to accept one BLOB. The values for the @FORM variables used in the parameters for the webjects can be supplied through a form like the form described in the previous section.
|
You must set the BLOB_COUNT parameter to 0 for every webject except for the webject you want the BLOBS to be delivered to.
|
The example task assumes that the database table contains the following columns:
• The NAME column contains the name of the BLOB.
• The FILECONTENT column contains the BLOB data.
The code for the example task is as follows:
<%@page language="java" session="false"%>
<%@ taglib uri="http://www.ptc.com/infoengine/taglib/core"
prefix="ie" %>
<!--
Upload a file from the browser and save in an oracle
blob column.
--/>
<ie:webject name="Do-Sql" type="ACT">
<ie:param name="INSTANCE" data="$(FORM[]instance[])"
default="jdbcAdapter"/>
<ie:param name="SQL"
data="DELETE FROM BLOBTEST WHERE NAME=
'$(FORM[]filename[0])'"/>
<ie:param name="CLASS" data="BLOBTEST"/>
<ie:param name="GROUP_OUT" data="TEMP"/>
<ie:param name="BLOB_COUNT" data="0"/>
</ie:webject>
<ie:webject name="Do-Sql" type="ACT">
<ie:param name="INSTANCE" data="$(FORM[]instance[])"
default="jdbcAdapter"/>
<ie:param name="SQL"
data="INSERT INTO BLOBTEST VALUES
('$(FORM[]filename[0])', EMPTY_BLOB())"/>
<ie:param name="CLASS" data="BLOBTEST"/>
<ie:param name="GROUP_OUT" data="TEMP"/>
<ie:param name="BLOB_COUNT" data="0"/>
</ie:webject>
<ie:webject name="Put-Blob-Stream" type="OBJ">
<ie:param name="INSTANCE" data="$(FORM[]instance[])"
default="jdbcAdapter"/>
<ie:param name="CLASS" data="BLOBTEST"/>
<ie:param name="ATTRIBUTE" data="FILECONTENT"/>
<ie:param name="WHERE"
data="(NAME='$(FORM[]filename[0])')"/>
<ie:param name="GROUP_OUT" data="TEMP"/>
</ie:webject>
Using Form Variables for Downloading BLOBs
The following example code produces explanatory text and a form for selecting a row from a database table containing a BLOB. Clicking “Retrieve” invokes an Info*Engine task that selects the corresponding row from the database table and returns the BLOB it contains:
<%@page language="java" session="false" errorPage="../IEError.jsp"%>
<%@ taglib uri="http://www.ptc.com/infoengine/taglib/core" prefix="ie" %>
<html>
<head><title>Send Blob</title>
</head>
<body>
<P>This page prompts for a "name" of the BLOB file to retrieve from an
database and a "MIME type" to associate with the BLOB file. The
"name" is used to select a row in the table where the BLOB is
stored. The table must be created and BLOBs uploaded to rows in
the table before this example is run. The table could be
created using a SQL statement like 'CREATE TABLE BLOBTEST
(NAME VARCHAR(60),FILECONTENT BLOB)'.
<H2>Download File from BLOB Column</H2>
<P>The MIME type determines which application is opened when the BLOB is
received.The MIME type is not stored in the table. Enter one of the
following MIME types:
<blockquote>'text/plain'<br>
'application/msword'<br>
'application/msexcel'<br>
'application/vnd.ms-excel'<br>
'image/gif'</blockquote>
<P>Include the single quotes in your MIME Type entry.</p>
<form method="POST" action="/Windchill/servlet/IE/tasks/com/company/DownloadBlob.xml"
enctype="multipart/form-data">
<TABLE><tr> <td align=right>
<B><FONT FACE=arial,helvetica>Adapter Instance:
</td>
<td>
<INPUT name = "instance" type="text" size=50>
</td>
</tr>
<tr> <td align=right>
<B><FONT FACE=arial,helvetica>Name:
</td>
<td>
<INPUT name = "filename" type="text" size=50>
</td>
</tr>
<tr> <td align=right>
<B><FONT FACE=arial,helvetica>Mime Type:
</td>
<td>
<INPUT name = "mimetype" type="text" size=50>
</td>
</tr>
<tr> <td align=right>
<INPUT type=submit NAME="submit" VALUE="Retrieve" id=button>
</td>
</tr></TABLE></form></body></html>
The DownloadBlob.xml task identified in the action attribute of the form element is the task that the Info*Engine server executes to download the BLOB. This task (which is described in the next section) uses form variables to identify the adapter instance, specify the name that corresponds to the BLOB in the table row where the BLOB is stored, and set the MIME type.
Example: BLOB Download Task
The following DownloadBlob.xml example task contains one adapter webject. This webject downloads one BLOB to the web browser. The MIME type specified in the MIMETYPE parameter is passed back to the browser and determines which application the browser launches to display the BLOB. The values for the @FORM variables used in the parameters for the webject can be supplied through a form like the form used in the previous section.
The example task assumes that the database table contains the following columns:
• The NAME column contains the name of the BLOB.
• The FILECONTENT column contains the BLOB data.
<%@page language="java" session="false"%>
<%@ taglib uri="http://www.ptc.com/infoengine/taglib/core"
prefix="ie" %>
<!--
Possible MIME Types
application/msword
text/plain
application/msexcel
application/vnd.ms-excel
--/>
<ie:webject name="Send-Blob-Stream" type="OBJ">
<ie:param name="INSTANCE" data="$(FORM[]instance[])"
default="jdbcAdapter"/>
<ie:param name="CLASS" data="BLOBTEST"/>
<ie:param name="ATTRIBUTE" data="FILECONTENT"/>
<ie:param name="MIMETYPE" data="$(FORM[]mimetype[0])"/>
<ie:param name="WHERE"
data="(NAME='$(FORM[]filename[0])')"/>
<ie:param name="GROUP_OUT" data="STATUS"/>
</ie:webject>