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.
Related
This question already has answers here:
Recommended way to save uploaded files in a servlet application
(2 answers)
Closed 6 years ago.
$uploads_dir = '/uploads';
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
// basename() may prevent filesystem traversal attacks;
// further validation/sanitation of the filename may be appropriate
$name = basename($_FILES["pictures"]["name"][$key]);
move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
}
This is how to upload images using PHP. Is there same function for JAVA. I want to upload image and save it in folder but using JAVA.
The action should happened on form submit.
No servlet for this upload
This might help: copies all files from one folder to another :
/**
* Copy files from one directory to another.
* #param sourceFile
* #param destFile
* #throws IOException
*/
public static void copyAllDirFiles(File fromDir, File toDir)
throws IOException {
//check if source is a directory
if (!fromDir.isDirectory()) {
throw new IOException(fromDir + " directory not found.");
}
//if destination does not exit, create it
if (!toDir.exists()) {
toDir.mkdir();
}
//get files from source
File[] files = fromDir.listFiles();
for (File file : files) {
InputStream in = new FileInputStream(file);
OutputStream out = new FileOutputStream(toDir + "/"
+ file.getName());
// Copy the bits from input stream to output stream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}
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?
I have a rather large database that ships with my app. I'm having a lot of trouble getting it to properly create itself on the local device, so I figure with the issues and it being so large, it might make more sense to host it on a server and work with it from there.
The database is 40 MB or less. What is the best way to manage this with it hosted somewhere?
The problem is with Database file size. You can make a Zip of your Database file and then copy it to your local path from Assets.
Here is the link: Copy Db File From Assets
Now, in that code replace the copyDataBase() function with the below one.
private void copyDataBase() throws IOException {
try {
InputStream mInputStream = mContext.getAssets().open(DB_NAME_ZIP);
String outFileName = DB_PATH + DB_NAME_ZIP;
OutputStream mOutputStream = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = mInputStream.read(buffer)) > 0) {
mOutputStream.write(buffer, 0, length);
}
ZipFile mZipFile = new ZipFile(DB_PATH + DB_NAME_ZIP);
InputStream nInputStream = mZipFile.getInputStream(mZipFile.getEntry(DB_NAME));
OutputStream nOutputStream = new FileOutputStream(DB_PATH + DB_NAME);
while ((length = nInputStream.read(buffer)) > 0) {
nOutputStream.write(buffer, 0, length);
}
nOutputStream.flush();
nOutputStream.close();
nInputStream.close();
// Close the streams
mOutputStream.flush();
mOutputStream.close();
mInputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
//Delete Zip file to minimize memory usage
final String mPath = DB_PATH + DB_NAME_ZIP;
final File file = new File(mPath);
if (file.exists())
file.delete();
}
}
Here DB_NAME_ZIP is the Database Zip file what you put in Assets folder like Android.zip but it actually contains Android.sqlite or Android.db.
I hope this one can help you.
I want to write a couple of methods in a Java package, which would be deployed in a UNIX Server.
As of now, my code was for Windows Server, for which I used the following code to zip Directory.
public static final void zipDirectory(File fBatchDirectory, String batchName, String ondemandDocExtension) throws IOException
{
//Set zip file name
File zip = new File(fBatchDirectory + "\\" + StringUtils.replace(batchName,".ind", "") + ".zip");
//filter file
FileFilter filter = new FileFilter(ondemandDocExtension);
File[] files = fBatchDirectory.listFiles(filter);
if(files.length > 0)
{
ZipOutputStream zos = new ZipOutputStream( new FileOutputStream(zip) );
zip(files, fBatchDirectory, zos , ondemandDocExtension);
zos.close();
}
}
private static final void zip(File[] files, File base,ZipOutputStream zos , String docExtension) throws IOException
{
byte[] buffer = new byte[8192];
int read = 0;
for (int i = 0, n = files.length; i < n; i++)
{
//Add to zip only if its file
if (files[i].isFile())
{
FileInputStream in = new FileInputStream(files[i]);
ZipEntry entry = new ZipEntry(files[i].getPath().substring(base.getPath().length() + 1));
zos.putNextEntry(entry);
while (-1 != (read = in.read(buffer)))
{
zos.write(buffer, 0, read);
}
in.close();
}
}
}
I am confused as to how to replicate the same functionality to zip Directory in Java, for UNIX?
And then I want to FTP the files from a UNIX Serve to another UNIX Server.
Any pointers would be greatly appreciated.
At a first glance, the only problem I see is at this line:
File zip = new File(fBatchDirectory + "\\" + StringUtils.replace(batchName,".ind", "") + ".zip");
Because you are explicitly using the double backslash (\\) in your filename. If you change that for File.separator your code should work for both operating systems:
File zip = new File(fBatchDirectory + File.separator + StringUtils.replace(batchName,".ind", "") + ".zip");
For the FTP part of it, you can get down and dirty and use an FTP client or use a more high level library like Apache Commons VFS which, by the way, inspired the new IO FileSystem API in Java 7, but I don't now about any library implementing the FTP protocol with the new API at the moment.
I want to copy a file from a jar. The file that I am copying is going to be copied outside the working directory. I have done some tests and all methods I try end up with 0 byte files.
EDIT: I want the copying of the file to be done via a program, not manually.
First of all I want to say that some answers posted before are entirely correct, but I want to give mine, since sometimes we can't use open source libraries under the GPL, or because we are too lazy to download the jar XD or what ever your reason is here is a standalone solution.
The function below copy the resource beside the Jar file:
/**
* Export a resource embedded into a Jar file to the local file path.
*
* #param resourceName ie.: "/SmartLibrary.dll"
* #return The path to the exported resource
* #throws Exception
*/
static public String ExportResource(String resourceName) throws Exception {
InputStream stream = null;
OutputStream resStreamOut = null;
String jarFolder;
try {
stream = ExecutingClass.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
if(stream == null) {
throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
}
int readBytes;
byte[] buffer = new byte[4096];
jarFolder = new File(ExecutingClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath().replace('\\', '/');
resStreamOut = new FileOutputStream(jarFolder + resourceName);
while ((readBytes = stream.read(buffer)) > 0) {
resStreamOut.write(buffer, 0, readBytes);
}
} catch (Exception ex) {
throw ex;
} finally {
stream.close();
resStreamOut.close();
}
return jarFolder + resourceName;
}
Just change ExecutingClass to the name of your class, and call it like this:
String fullPath = ExportResource("/myresource.ext");
Edit for Java 7+ (for your convenience)
As answered by GOXR3PLUS and noted by Andy Thomas you can achieve this with:
Files.copy( InputStream in, Path target, CopyOption... options)
See GOXR3PLUS answer for more details
Given your comment about 0-byte files, I have to assume you're trying to do this programmatically, and, given your tags, that you're doing it in Java. If that's true, then just use Class.getResource() to get a URL pointing to the file in your JAR, then Apache Commons IO FileUtils.copyURLToFile() to copy it out to the file system. E.g.:
URL inputUrl = getClass().getResource("/absolute/path/of/source/in/jar/file");
File dest = new File("/path/to/destination/file");
FileUtils.copyURLToFile(inputUrl, dest);
Most likely, the problem with whatever code you have now is that you're (correctly) using a buffered output stream to write to the file but (incorrectly) failing to close it.
Oh, and you should edit your question to clarify exactly how you want to do this (programmatically, not, language, ...)
Faster way to do it with Java 7+ , plus code to get the current directory:
/**
* Copy a file from source to destination.
*
* #param source
* the source
* #param destination
* the destination
* #return True if succeeded , False if not
*/
public static boolean copy(InputStream source , String destination) {
boolean succeess = true;
System.out.println("Copying ->" + source + "\n\tto ->" + destination);
try {
Files.copy(source, Paths.get(destination), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
logger.log(Level.WARNING, "", ex);
succeess = false;
}
return succeess;
}
Testing it (icon.png is an image inside the package image of the application):
copy(getClass().getResourceAsStream("/image/icon.png"),getBasePathForClass(Main.class)+"icon.png");
About the line of code (getBasePathForClass(Main.class)): -> check the answer i have added here :) -> Getting the Current Working Directory in Java
Java 8 (actually FileSystem is there since 1.7) comes with some cool new classes/methods to deal with this. As somebody already mentioned that JAR is basically ZIP file, you could use
final URI jarFileUril = URI.create("jar:file:" + file.toURI().getPath());
final FileSystem fs = FileSystems.newFileSystem(jarFileUri, env);
(See Zip File)
Then you can use one of the convenient methods like:
fs.getPath("filename");
Then you can use Files class
try (final Stream<Path> sources = Files.walk(from)) {
sources.forEach(src -> {
final Path dest = to.resolve(from.relativize(src).toString());
try {
if (Files.isDirectory(from)) {
if (Files.notExists(to)) {
log.trace("Creating directory {}", to);
Files.createDirectories(to);
}
} else {
log.trace("Extracting file {} to {}", from, to);
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException e) {
throw new RuntimeException("Failed to unzip file.", e);
}
});
}
Note: I tried that to unpack JAR files for testing
Robust solution:
public static void copyResource(String res, String dest, Class c) throws IOException {
InputStream src = c.getResourceAsStream(res);
Files.copy(src, Paths.get(dest), StandardCopyOption.REPLACE_EXISTING);
}
You can use it like this:
File tempFileGdalZip = File.createTempFile("temp_gdal", ".zip");
copyResource("/gdal.zip", tempFileGdalZip.getAbsolutePath(), this.getClass());
Use the JarInputStream class:
// assuming you already have an InputStream to the jar file..
JarInputStream jis = new JarInputStream( is );
// get the first entry
JarEntry entry = jis.getNextEntry();
// we will loop through all the entries in the jar file
while ( entry != null ) {
// test the entry.getName() against whatever you are looking for, etc
if ( matches ) {
// read from the JarInputStream until the read method returns -1
// ...
// do what ever you want with the read output
// ...
// if you only care about one file, break here
}
// get the next entry
entry = jis.getNextEntry();
}
jis.close();
See also: JarEntry
To copy a file from your jar, to the outside, you need to use the following approach:
Get a InputStream to a the file inside your jar file using getResourceAsStream()
We open our target file using a FileOutputStream
We copy bytes from the input to the output stream
We close our streams to prevent resource leaks
Example code that also contains a variable to not replace the existing values:
public File saveResource(String name) throws IOException {
return saveResource(name, true);
}
public File saveResource(String name, boolean replace) throws IOException {
return saveResource(new File("."), name, replace)
}
public File saveResource(File outputDirectory, String name) throws IOException {
return saveResource(outputDirectory, name, true);
}
public File saveResource(File outputDirectory, String name, boolean replace)
throws IOException {
File out = new File(outputDirectory, name);
if (!replace && out.exists())
return out;
// Step 1:
InputStream resource = this.getClass().getResourceAsStream(name);
if (resource == null)
throw new FileNotFoundException(name + " (resource not found)");
// Step 2 and automatic step 4
try(InputStream in = resource;
OutputStream writer = new BufferedOutputStream(
new FileOutputStream(out))) {
// Step 3
byte[] buffer = new byte[1024 * 4];
int length;
while((length = in.read(buffer)) >= 0) {
writer.write(buffer, 0, length);
}
}
return out;
}
A jar is just a zip file. Unzip it (using whatever method you're comfortable with) and copy the file normally.
${JAVA_HOME}/bin/jar -cvf /path/to.jar