Java EE - Upload image to database? - java

I'm making a fairly basic site for my mother, and seeing as I did some stuff in Java EE and with EJB during college last semester, I'm going to stick to this.
The only issue I am having is uploading images - I can't seem to find any examples.
I'm using entity classes and parameterised queries. This is the code for writing to the database, which is working fine, I'm just setting the blob image value to null for the moment.
#Override
public void addClothes(String designer, String cname, String ctype, String desc) {
Clothes c = new Clothes();
em.persist(c);
c.setDesigner(designer);
c.setCname(cname);
c.setCtype(ctype);
c.setDescript(desc);
c.setImage(null);
}
I have a servlet that takes a file, I'm just not sure how the file, when passed, should be sorted and what I should write to the database (from what I'm seeing, it's byte[])
A hand in the right direction would be appreciated!

Once you have the file on the server, either in memory or in a local or temp file (that depends on the framework or libraries that you're using), you will have a reference of a wrapper type.
If you are using Apache Commons File Upload, you have a FileItem reference. For request all contents of the file as byte array:
byte[] contents = fileItem.get();
If you are using Tomahawk of Trinidad, you have a org.apache.myfaces.trinidad.model.UploadedFile reference. For request all contents of the file as byte array, you can use class IOUtils of the Apache Commons IO:
byte[] contents = IOUtils.toByteArray(uploadedFile.getInputStream());
Of if you have a reference of org.apache.myfaces.custom.fileupload.UploadedFile, is more simple:
byte[] contents = uploadedFile.getBytes();
UPDATE
If you are using Java EE 6, you can use new features of Server 3.0 specification for upload files without extra libraries. See the excellent tutorial of BalusC in The BalusC Code: Uploading files in Servlet 3.0

To work with hibernatehttp://www.mkyong.com/hibernate/hibernate-save-image-into-database/
To work with JDBC:
To Write image into database BLOB using Jdbc , You need to Convert the File into Inputstream. statement.setBinaryStream(2, (InputStream) inputStream,(int) (image.length())); PreparedStatement statement offer method setBinaryStream() which is used to write binary stream into database BLOB column.
Here is a code snippet to help you:
File image = new File("C:/test.jpg");
inputStream = new FileInputStream(image);
Prepared statement = //define as per your table
// set the file binary stream
statement.setBinaryStream(2, (InputStream) inputStream,(int) (image.length()));
statement.executeUpdate();

In your Clothes class, you can add:
#Lob
private byte[] image;
// Getter/Setter methods

Got it working ! Somewhat, with this code:
public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
out = response.getWriter();
final String path = "clothesImages" + File.separator + request.getParameter("designer") + File.separator + request.getParameter("ctype") + File.separator + request.getParameter("cname");
out.println(path);
String currentDir = new File(".").getAbsolutePath();
out.println(currentDir);
final Part filePart = request.getPart("image");
final String filename = "image.jpg";
File file = new File(path);
if (!file.exists()){
out.println("Dir Doesn't Exist");
file.mkdirs();
}
OutputStream outstream = null;
InputStream filestream = null;
try{
outstream = new FileOutputStream(new File(path + File.separator + filename));
filestream = filePart.getInputStream();
int read = 0;
final byte[] bytes = new byte[1024];
while(( read = filestream.read(bytes)) != -1){
outstream.write(bytes, 0, read);
}
out.println("New file " + filename + " created at " + path);
}catch (FileNotFoundException fne) {
out.println("You either did not specify a file to upload or are "
+ "trying to upload a file to a protected or nonexistent "
+ "location.");
out.println("<br/> ERROR: " + fne.getMessage());
}finally {
if (out != null) {
out.close();
}
if (filestream != null) {
filestream.close();
}
if (outstream != null) {
outstream.close();
}
}
}
The only issue I have is setting the file path. The path is
C:\Users\Chris\AppData\Roaming\NetBeans\7.2.1\config\GF3\domain1\
But I want it to save in
Project-war/web/images
Any ideas?

Related

Backup and Restore HsqlDb Embeded File (NOT DATABASE)

Every one talk about Backup Hsqldb outside, but what i require is to Backup the embeded files...
I'm using Spring JPA, and the application is always running, so files are in use, also since there is no DBMS, i'm wonder if there are ways to backup and restore?
If there are, please guide me...
Otherwise, i though of copying database file, after somehow (don't know how) putting spring JPA in offline mode, and then ZIP those file, which i don't know in java, and then let user to download it, if spring allow's it... somehow (as i use stand alone spring boot, which is a single file, and it doesn't offer lot of those fancy folder, which we can point to them as website url...)
In the end in any scenario i want to send the file to client.
Sorry if i know none of this, i came from C#, and after 5 years, it's my second time using Java, which i never beem pro in it.
UPDATE
Although i'm not sure if i can make a zip file from running database, and store it in that place... I write this code through searching, i find several method that returns current directory, but non of them point to directory i want... one of them, in debug it point to very inner location, like targer/class/x/y/z, after i package it to jar file, it may be different, another one point to C/..../temp, ... i need to get write to where my DB file is located, then pass those file to make zip file function, and tell user to download the files
#RestController
#RequestMapping(value = "/rest/database-manager")
public class DatabaseManager {
private ServletContext servletContext;
private final Environment env;
#Autowired
public DatabaseManager(Environment env, ServletContext servletContext) {
this.env = env;
this.servletContext = servletContext;
}
#RequestMapping(value = "/get-backup", method=RequestMethod.GET)
private FileSystemResource getBackup() throws IOException {
//String directory = DemoApplication.class.getResource("").getPath();
String outputLocation = servletContext.getRealPath("./");
String dataBaseFilePath = servletContext.getRealPath(env.getProperty("application.database-file-location"));
Calendar cal = new GregorianCalendar();
String zipFile = outputLocation + "/backup-"
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.YEAR)), 4, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.MONTH)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)), 2, "0")
+ "-"
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.HOUR)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.MINUTE)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.SECOND)), 2, "0")
+ ".zip";
ZipUtil.ToZip(new String[]{""}, zipFile);
return new FileSystemResource(zipFile);
}
}
zip function:
public class ZipUtil {
public static void ToZip(String inputFiles[], String outputFile) throws IOException {
//create byte buffer
byte[] buffer = new byte[1024];
/*
* To create a zip file, use
*
* ZipOutputStream(OutputStream out)
* constructor of ZipOutputStream class.
*/
//create object of FileOutputStream
FileOutputStream fout = new FileOutputStream(outputFile);
//create object of ZipOutputStream from FileOutputStream
ZipOutputStream zout = new ZipOutputStream(fout);
for (int i = 0; i < inputFiles.length; i++) {
//create object of FileInputStream for source file
FileInputStream fin = new FileInputStream(inputFiles[i]);
/*
* To begin writing ZipEntry in the zip file, use
*
* void putNextEntry(ZipEntry entry)
* method of ZipOutputStream class.
*
* This method begins writing a new Zip entry to
* the zip file and positions the stream to the start
* of the entry data.
*/
zout.putNextEntry(new ZipEntry(inputFiles[i]));
/*
* After creating entry in the zip file, actually
* write the file.
*/
int length;
while ((length = fin.read(buffer)) > 0) {
zout.write(buffer, 0, length);
}
/*
* After writing the file to ZipOutputStream, use
*
* void closeEntry() method of ZipOutputStream class to
* close the current entry and position the stream to
* write the next entry.
*/
zout.closeEntry();
//close the InputStream
fin.close();
}
//close the ZipOutputStream
zout.close();
}
}
Full Answer:
I'm not sure if produce do anything, as i directly write into response inside, and return void.
My Response Method:
#RequestMapping(value = "/get-backup", method = RequestMethod.GET)
private void getBackup(HttpServletResponse response) throws IOException {
/*//String directory = DemoApplication.class.getResource("").getPath();
String outputLocation = servletContext.getRealPath("./");
String dataBaseFilePath = servletContext.getRealPath(env.getProperty("application.database-file-location"));
Calendar cal = new GregorianCalendar();
String zipFile = outputLocation + "/backup-"
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.YEAR)), 4, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.MONTH)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)), 2, "0")
+ "-"
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.HOUR)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.MINUTE)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.SECOND)), 2, "0")
+ ".zip";
SQLQuery query = session.createSQLQuery("BACKUP DATABASE TO '/tmp/backup.tar.gz' BLOCKING");
query.executeUpdate();*/
File zipFile = null;
Calendar cal = new GregorianCalendar();
String prefix = "DBK-"
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.YEAR)), 4, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.MONTH)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)), 2, "0")
+ "-"
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.HOUR)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.MINUTE)), 2, "0")
+ StrMgr.leftPad(String.valueOf(cal.get(Calendar.SECOND)), 2, "0");
String suffix = ".tar.gz";
zipFile = File.createTempFile(prefix, suffix);
zipFile.delete();
databaseManagerRepository.Backup(zipFile.getAbsolutePath());
response.setContentType("application/gzip");
response.setHeader("Content-disposition", "attachment; filename=" + zipFile.getName());
// OutputStream out = response.getOutputStream();
// FileInputStream in = new FileInputStream(zipFile);
/*
* copy from in to out
*/
OutputStream out = null;
FileInputStream in = null;
try {
out = response.getOutputStream();
in = new FileInputStream(zipFile);
byte[] buffer = new byte[4096]; // To hold file contents
int bytes_read; // How many bytes in buffer
// Read a chunk of bytes into the buffer, then write them out,
// looping until we reach the end of the file (when read() returns
// -1). Note the combination of assignment and comparison in this
// while loop. This is a common I/O programming idiom.
while ((bytes_read = in.read(buffer)) != -1)
// Read until EOF
out.write(buffer, 0, bytes_read); // write
}
catch (Exception ex){
System.out.print(ex.getMessage());
}
// Always close the streams, even if exceptions were thrown
finally {
if (in != null)
try {
in.close();
} catch (IOException e) {
;
}
if (out != null)
try {
out.close();
} catch (IOException e) {
;
}
}
zipFile.delete();
}
My Backup Native SQL Action Executor
#Repository
public class DatabaseManagerRepository {
#PersistenceContext
private EntityManager entityManager;
/*The query force us to use transaction, and since the DB is online and we use spring, it also force us to use spring transaction*/
#Transactional(rollbackFor = {Exception.class})
public void Backup(String outputDir) {
//NOT BLOCKING -> For large database, backup is performed while the database perform other operations
//AS FILES -> We only define directory not the file itself
Query q = entityManager.createNativeQuery("BACKUP DATABASE TO '" + outputDir + "' BLOCKING"/*" AS FILES"*/);
q.executeUpdate();
}
}
Backup is the same with an HSQLDB Server or embedded database. You execute the SQL statement:
BACKUP DATABASE TO <directory name> BLOCKING AS FILES
The directory name is a path to the target directory to store the backup files. For example BACKUP DATABASE TO 'C://db_backups/' BLOCKING AS FILES
http://hsqldb.org/doc/2.0/guide/management-chapt.html#mtc_online_backup
The AS FILES backup database creates a set of files which you can zip.

Import csv file to mysql through jsp servlet

I am writing a web app that I would like to be able to import a csv file into a database from a jsp. Previously I have used the following code to insert the csv into the database.
LOAD DATA LOCAL INFILE "/myFileLocation.csv"
INTO TABLE myTable
COLUMNS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
ESCAPED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES;
Which works great when I have the file locally.
My question, when I upload the csv file in my jsp as a multipart. Is it possible for me to pass that PartItem file as a variable and replace the "/myFileLocation.csv" with the PartItem files temp location?
I can see the temp location when I debug and view the PartItem file which resides in repository/path under the variables table. Is this at all possible to access or do i need to parse the csv and insert it into the database that way?
I ended up finding a way to make this work. Not sure if it's the best solution but its working as I envisioned. Basically I create a string pointing to an assets folder I created in the web/resources like this.
final String mainPath = this.getServletContext().getRealPath("resources/assets");
Then I read the uploaded file, check to see if the file already exists in my assets folder, if it does I delete it.
Part filePart = request.getPart("csvFile");
String path = mainPath + "/" + filePart.getSubmittedFileName();
File fileTemp = new File(path);
if(fileTemp.exists()){
fileTemp.delete();
}
Lastly I read the uploaded file and write a new file in the location I directed it to which in this case is the assets folder I created like this.
final String fileName = filePart.getSubmittedFileName();
File convFile = new File(filePart.getSubmittedFileName());
FileOutputStream fos = new FileOutputStream(convFile);
OutputStream out = null;
InputStream filecontent= null;
try{
out = new FileOutputStream(new File(mainPath + File.separator + fileName));
filecontent = filePart.getInputStream();
int read = 0;
final byte[] bytes = new byte[1024];
while((read = filecontent.read(bytes)) != -1){
out.write(bytes, 0, read);
}
} catch (FileNotFoundException fne) {
} finally {
if (out != null) {
out.close();
}
if (filecontent != null) {
filecontent.close();
}
}
After that I just passed a string containing the path to the file with the file name to the DAO I created where I was able to utilize the sql statement I had posted above.
Like I stated before, not sure if this is the best way to do this but it seems to be working fine for me and none of my java code is contained within my jsp. If anyone has a better way of doing this or sees something wrong with what I did here let me know, I'd be very interested to hear about it.

Unzipped DB in Android not readable

I am trying to transfer a SQLite database into an app by downloading it and then unzipping it to the correct location. I was successful in transferring the DB when it was unzipped. The error I get is that it cannot find any of the tables I query. I have also been successful in unzipping and reading normal text files.
The DB has Hebrew and English, but that has not caused problems before. The bilingual DB was copied successfully when it was not zipped and bilingual texts have been successfully unzipped and read. Still, it is a possibility that there is an encoding problem going on. That seems weird to me, because as you can see below in the code, I'm just copying the bytes directly.
-EDIT-
Let's say the prezipped db is called test1.db. I zipped it, put it in the app, unzipped it and called that test2.db. when I ran a diff command on these two, there were no differences. So there must be a technical issue with the way android is reading the file / or maybe encoding issue on android that doesn't exist on pc?
I hate to do a code dump, but i will post both my copyDatabase() function (which works). That is what I used previously running it on an unzipped DB file. I put it here as comparison. Now I'm trying to use unzipDatabase() function (which doesn't work), and use it on a zipped DB file. The latter function was copied from How to unzip files programmatically in Android?
private void copyDatabase() throws IOException{
String DB_NAME = "test.db";
String DB_PATH = "/data/data/org.myapp.myappname/databases/";
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
private boolean unzipDatabase(String path)
{
String DB_NAME = "test.zip";
InputStream is;
ZipInputStream zis;
try
{
String filename;
is = myContext.getAssets().open(DB_NAME);
zis = new ZipInputStream(is);
ZipEntry ze;
byte[] buffer = new byte[1024];
int count;
while ((ze = zis.getNextEntry()) != null)
{
// write to a file
filename = ze.getName();
// Need to create directories if not exists, or
// it will generate an Exception...
if (ze.isDirectory()) {
Log.d("yo",path + filename);
File fmd = new File(path + filename);
fmd.mkdirs();
continue;
}
OutputStream fout = new FileOutputStream(path + filename);
// reading and writing zip
while ((count = zis.read(buffer)) != -1)
{
fout.write(buffer, 0, count);
}
fout.flush();
fout.close();
zis.closeEntry();
}
zis.close();
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
So still don't know why, but the problem is solved if I first delete the old copy of the database (located at DB_PATH + DB_NAME) and then unzip the new one there. I didn't need to do this when copying it directly.
so yay, it was a file overwriting issue...If someone knows why, feel free to comment

How to offer download of local PDF file in Java?

I have JBoss running as application server and somewhere on my HD there is a PDF file, that gets created when the user clicks on a specific action. Let's say the file is here: C:/PDF/doonot/10.07.2012/doonot.pdf. How can I offer this file as download? I already did it for a CSV file, but I don't know how to do it with PDF.
Any help is much appreciated.
as i wrote on Is there a common way to download all types of files in jsp?
you can use something like this:
public HttpServletResponse getFile (HttpServletRequest request ,HttpServletResponse httpServletResponse, .......){
HttpServletResponse response = httpServletResponse;
InputStream in =/*HERE YOU READ YOUR FILE AS BinaryStream*/
String filename = "";
String agent = request.getHeader("USER-AGENT");
if (agent != null && agent.indexOf("MSIE") != -1)
{
filename = URLEncoder.encode(/*THIS IS THE FILENAME SHOWN TO THE USER*/, "UTF8");
response.setContentType("application/x-download");
response.setHeader("Content-Disposition","attachment;filename=" + filename);
}
else if ( agent != null && agent.indexOf("Mozilla") != -1)
{
response.setCharacterEncoding("UTF-8");
filename = MimeUtility.encodeText(/*THIS IS THE FILENAME SHOWN TO THE USER*/, "UTF8", "B");
response.setContentType("application/force-download");
response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
}
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
byte by[] = new byte[32768];
int index = in.read(by, 0, 32768);
while (index != -1) {
out.write(by, 0, index);
index = in.read(by, 0, 32768);
}
out.flush();
return response;
}
UPDATE:
Dont forget that you can use the InputStream as this:
// read local file into InputStream
InputStream inputStream = new FileInputStream("c:\\SOMEFILE.xml");
or you can use it even like this
//read from database
Blob blob = rs.getBlob(1);
InputStream in = blob.getBinaryStream();
You can simply write a servlet wich read the pdf and write it to the response output stream.
Exemple here : http://www.java-forums.org/blogs/servlet/668-how-write-servlet-sends-file-user-download.html
Yes Gustav is right. Java doesn't discriminate amongst file types. A file is a file, if you did it for csv, it should also work for pdf.

How to use java.util.zip to archive/deflate string in java for use in Google Earth?

Use Case
I need to package up our kml which is in a String into a kmz response for a network link in Google Earth. I would like to also wrap up icons and such while I'm at it.
Problem
Using the implementation below I receive errors from both WinZip and Google Earth that the archive is corrupted or that the file cannot be opened respectively. The part that deviates from other examples I'd built this from are the lines where the string is added:
ZipEntry kmlZipEntry = new ZipEntry("doc.kml");
out.putNextEntry(kmlZipEntry);
out.write(kml.getBytes("UTF-8"));
Please point me in the right direction to correctly write the string so that it is in doc.xml in the resulting kmz file. I know how to write the string to a temporary file, but I would very much like to keep the operation in memory for understandability and efficiency.
private static final int BUFFER = 2048;
private static void kmz(OutputStream os, String kml)
{
try{
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(os);
out.setMethod(ZipOutputStream.DEFLATED);
byte data[] = new byte[BUFFER];
File f = new File("./icons"); //folder containing icons and such
String files[] = f.list();
if(files != null)
{
for (String file: files) {
LOGGER.info("Adding to KMZ: "+ file);
FileInputStream fi = new FileInputStream(file);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(file);
out.putNextEntry(entry);
int count;
while((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
}
ZipEntry kmlZipEntry = new ZipEntry("doc.kml");
out.putNextEntry(kmlZipEntry);
out.write(kml.getBytes("UTF-8"));
}
catch(Exception e)
{
LOGGER.error("Problem creating kmz file", e);
}
}
Bonus points for showing me how to put the supplementary files from the icons folder into a similar folder within the archive as opposed to at the same layer as the doc.kml.
Update Even when saving the string to a temp file the errors occur. Ugh.
Use Case Note The use case is for use in a web app, but the code to get the list of files won't work there. For details see how-to-access-local-files-on-server-in-jboss-application
You forgot to call close() on ZipOutputStream. Best place to call it is the finally block of the try block where it's been created.
Update: To create a folder, just prepend its name in the entry name.
ZipEntry entry = new ZipEntry("icons/" + file);

Categories