Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

display of picture from database using JSP

Status
Not open for further replies.

Bangal

Programmer
Sep 18, 2003
9
0
0
SG
I need to display a picture which I have saved in a database as a BLOB. Can anyone tell me if these codes are done correctly? Now, when I run, I get no errors however, its just a blank page. How do I allow the user to see my picture file?

Im using mySQL server.
Program is Sun ONE Studio (JSP)

For the uploading part, i used a java bean given by another website. So now, I only need to handle the download part. Please give me your advice. Thanks.


<% String url = "jdbc:mysql://localhost/test";
String userID="root";
String PWD="";
Connection conn = null;
String classPath= "com.mysql.jdbc.Driver";

try{
Class.forName(classPath).newInstance();
conn = DriverManager.getConnection(url,userID,PWD);
}catch(Exception exc){
out.println(exc.toString());
}
Statement stm = null;
ResultSet rst = null;

stm=conn.createStatement();

String strSQL = "SELECT binaryfile FROM uploads WHERE filename='baby.gif'";
rst = stm.executeQuery(strSQL);

if (rst.next()){
byte [] barray = rst.getBytes("binaryfile");

FileOutputStream fo = new FileOutputStream("display.gif");

for(int i=0; i < barray.length;i++){
fo.write(barray);
}
fo.close();

FileInputStream fi = new FileInputStream("display.gif");
int size = fi.available();
for (int i = 0; i <=size; i++){
System.out.print((char)fi.read());
}
fi.close();
}
rst.close();
stm.close();
conn.close();
%>

 
Couple of things :

Why are you writing the blob out to a file, and then reading it back in again from that file ?

When you read the file with blob in it, you are just printing out the data to System.out (and you are converting the bytes to chars, which is not what you want to do).

When display byte data within a JSP, you will run into big problems, because you need a method that is capable of writing byte[] array data, but within JSP, the output stream is already called, and is cast to a JspWriter class, which cannot write byte data. I suppose you could use the JspWriter.print(byte) and a loopm but thats a bit naff.

You would be much better off to have a servlet that reads the blob from the db, and then sets the response's content-type to the correct mime time (ie image/gif ), and then write out the byte[] array all in one go - without writing the blob to a file.

You can then embed the servlet call in html like this :

<embed src="
 
Is writing a JSP and a servlet similar?
I have never written servlets.
My purpose is just to display a picture. However, its the first time I am trying it.
What actually do we have to do in order to display the picture from the database?

Query Codes
String strSQL = "SELECT binaryfile FROM uploads WHERE filename='baby.gif'";
rst = stm.executeQuery(strSQL);

Putting the Byte In an Array
byte [] barray = rst.getBytes("binaryfile");

After this step, I am not very sure of what to do too.
Do I convert the bytes to another data type?

Previously I used these codes...
response.setContentType("image/bmp"); <-- this is what u meant by "sets the response's content-type to the correct mime time (ie image/gif )"

ServletOutputStream op = response.getOutputStream();
for(int i=0;i<Integer.parseInt(dim_image);i++)
{
op.write(blocco);
}


I don't know if I am at the right track coz there were programmers who commented this "another note; your writing code is horribly inefficient; theres no need to write single bytes at a time, and parse a string to an integer every single time you work:"
So what actually is the right way? I'm a little confused at how to do these. Its the first time I'm handing binary data as I only used to interact with simple database types...
Please show me the ropes.. thanks.
 
JSP pages are compiled into servlets by the servlet container (ie Tomcat), but you can also write your own.

Try this :

1) Your servlet -
Code:
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
import java.sql.*;

public class ImageServlet extends HttpServlet {

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			
			String filename = request.getParameter("filename");
			
			
			//execute you sql to get the clob here
			Connection c = ...
			Statement s = c.createStatement();
			String strSQL = "SELECT binaryfile FROM uploads WHERE filename='" +filename +"'";
			rst = stm.executeQuery(strSQL);
			byte [] barray = rst.getBytes("binaryfile");
			rst.close();
			s.close();
			response.setContentType("image/gif");
			response.getOutputStream().write(barray);

		} catch (Exception sqle) {

		}

	}

}

2) And then in your JSP, have this html :

Code:
<embed src="[URL unfurl="true"]http://localhost:8080/servlet/ImageServlet"[/URL] content="image/gif">
 
After putting the codes and after running, there is a small square there. But the square is empty. No picture comes out.

Is it a better idea to save the file to disk during upload and store the link in the database. And when I need to display it, I just take the link out from the database and put it in img src?

Actually what does the servlet above do?
 
Yes it is always a bad idea to store blobs inside of a database. One of the most obvious reasons is because it will make your database size grow quickly. And if you need to perform things such as backup and fail over restors it could be a timely process restoring a database with blobs in it. I just finished writing a servlet to extract 1,000,000 image blobs from my companies db and store them on the file syste, and then update a pointer to the images relative storage path.

Doing this will also cut down on hits on the db which could lead to performance issues later down the road. And once you have the image extracted you just have to read in the byte stream and build a servlet to display the byte stream.

I would suggest looking into removing storing blobs on the file system, then write a servlet that has an image viewer in it. It is not that hard and there is plenty of information out there on how to do both.

I would search java.sun.com for both!!!!! (hint, hint)

Later

 
But I only need to store less than 100 images. What I'm trying now is to upload the picture into a folder in the server while saving the link into the database. Thus, the displaying will be much more easier as its a direct link. In this way, I have to give up the UploadBean at javazoom.net and to write my own. But I do not have any other links to go and and learn myself. Can anyone suggest me any links where I can learn how to write to upload a bean myself? The example sedj gave me can be compiled but it can run. However, no picture came out n I don't know wheres the fault.
 
Bangal :

Debug the code ! Add in System.out calls to check oprations are performing what you expect. I promise you, the concept that I displayed in the code is sound, I expect its just a silly error you are getting.

Check that the image byte data is being extracted correctly. Save the byte data as a file as a test to see that the image data is valid, check that the <embed> tag, if you are using it, is calling the correct URL ...
 
Thanks for sedj for assuring me.
I have tried to compile the whole servlet and it managed to compile successfully.
How do I ensure that it is the right URL?
Its the format of
<embed src = " content="image/gif">

hostname: localhost
port: 8080 (but when i run, the url states 8081)
Name of Servlet: ImageServlet
Content: "image/gif"

Whats the center 'servlet' mean?
does it mean that its a servlet? or do i have to store it in a folder called servlet?

I read from a website about embed src..
"The file server on which the embedded object resides must MIME encode files of the type to be embedded or the embed will fail. "
Have I MIME encode files?
 
gif images are mapped to the MIME type "image/gif" - this is why we do a :

response.setContentType("image/gif");

RE the URL ...

The servlet bit is only a mapping - it says nothing really about that it is a *Servlet* - its just the way I have always done it ...

If you put the servlet class in WEB-INF/classes, you need a web.xml file entry like this :

Code:
	<servlet>
	    <servlet-name>ImageServlet</servlet-name>
	    <servlet-class>ImageServlet</servlet-class>
	    <load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>ImageServlet</servlet-name>
		<url-pattern>/servlet/ImageServlet</url-pattern>
	</servlet-mapping>

This means that for any URL pattern matching "servlet/ImageServlet", your ImageServlet class in WEB-INF/classes will get called.

The URL above would work for the ROOT context, but if you had your own context like "mywebapp" then you would have to chnage the URL slightly to be :


This URL talks about the basics of webapp deployment, web.xml files, contexts and so on :

 
I only created a folder where there is no WEB-INF folder.
I created the jsp and the ImageServlet.class. But there are extra files beside there. These included:
ImageServlet (Java(tm) File (Forte(tm) For Java(tm)))
ImgeServlet.class
ImageServlet.java~
.nbattrs
displayPicture.jsp

So if I used the url as above, it shouldn't be a problem.
I wanted to try to debug but I couldn't. What I did was tried to add a line "System.out.println("done-A");" after some codings to ensure that the codes have been performed. But whatever I executed the JSP page, nothing comes out except a small square. Is it the right way to debug?
 
Yes, adding lines like "System.out.println("done-A");" is a good idea to let you know what is going on. Just try hitting the servlet in a browser to start with - don't try to use the <embed> tag in a JSP unless you are sure its working.

If you start tomcat using "catalina run" you should see the System.out messages in the console window.

If you start it with "catalina start" you should see the messages in "logs/launcher.server.log".
 
Do I execute the servlet itself or use another JSP to call it out? And if I use jsp to call it out, how do i do it?
using <a href=" content="image/gif">Start Servlet</a> ?
I'm using SunONE Studio 4 by the way.
At the Output Window, there is an error when I try executing the servlet.
It put there:
java.lang.NoClassDefFoundError:sedj/ImageServlet(wrong name: ImageServlet)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:502)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java;123)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:250)
at java.net.URLClassLoader.access$100(URLClassLoader.java:193)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:186)
at java.lag.ClassLoader.loadClass(ClassLoader.java:299)
at sun.misc.Launcher$AppClassLoader.loadClass(Launchher.java:265)
at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)
Exception in thread "main"

==============================
even if I put the system.out.println("aaa"); in front of this method, public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, there is still an error. So does the error lies with this line:public class ImageServlet extends HttpServlet?
 
This error is caused by the fact that it cannot find the class sedj.ImageServlet :

java.lang.NoClassDefFoundError:sedj/ImageServlet(wrong name: ImageServlet)

So looks like you need to add a line at the top of ImageServlet.java :

package sedj;

OR, take out the reference to "sedj".

Then try it again.
 
All along, I had a folder called FYP(FileSystem). And in it i had alot of JSP files.. I only created a folder called sedj and copied the two files inside. Thus, it created an error. Now, I took it out so that there is no more folder. The error message now have only:
java.lang.NoSuchMethodError:main
Exception in thread "main"

What I did was execute the servlet by itself.
===============================================
Servlet Codes

import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
import java.sql.*;

public class ImageServlet extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
System.out.println("hello");
String filename = request.getParameter("filename");
filename = "baby.gif";
//execute you sql to get the clob here
String url = "jdbc:mysql://localhost/test";
String userID="root";
String PWD="";
Connection conn = null;
String classPath= "com.mysql.jdbc.Driver";
System.out.println("hello");
try{
Class.forName(classPath).newInstance();
conn = DriverManager.getConnection(url,userID,PWD);
}catch(Exception exc){
System.out.println(exc.toString());
}
Statement stm = null;
ResultSet rst = null;

// Connection c = ...
stm = conn.createStatement();
String strSQL = "SELECT binaryfile FROM uploads WHERE filename='" +filename +"'";
rst = stm.executeQuery(strSQL);
byte [] barray = rst.getBytes("binaryfile");
System.out.println("A done");
response.setContentType("image/gif");
response.getOutputStream().write(barray);

rst.close();
stm.close();
conn.close();
} catch (Exception sqle) {
System.out.println(sqle.toString());
}

}

}
 
Yes, it is in the WEB-INF/Classes folder. But the error still remains the same.
 
Your sturcture should be like this :

TOMCAT_HOME/webapps/myContext (your context's root)
TOMCAT_HOME/webapps/myContext/WEB-INF (your web.xml goes here)
TOMCAT_HOME/webapps/myContext/WEB-INF/classes (your classes go here)

So with a structure like this, the URL would be :


as long as you have your ImageServlet mapped in web.xml like I showed you earlier.

Is this how it looks for you ?
 
Do you have servlet mapping turned on inside the web.xml file? If so, are you mapping the servlets without the ProjectName/servlet/ServletName "/servlet/" in the middle of the path?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top