In Java JSP, I'm using input stream and BLOB datatype to write any type of file into the database. I want to retrieve the BLOB file. How should I go about retrieving it? I tried using select statement and got this (material column).
Using a ResultSet, you can retrieve a java.sql.Blob instance:
Blob blob = resultSet.getBlob("MATERIAL");
Then you can open an input stream:
InputStream input = blob.getBinaryStream();
And write it to a file as described in Is it possible to create a File object from InputStream
Getting the Blob from the table:
try (ResultSet rs = statement.executeQuery(query)) {
if(rs.next()) {
fileBlob = rs.getBlob(1);
}
}
Saving the contents of the Blob into a new file:
try (InputStream ipStream = fileBlob.getBinaryStream(1, fileBlob.length());
OutputStream opStream = new FileOutputStream(new File("path/to/file"))) {
int c;
while ((c = ipStream.read()) > -1) {
opStream.write(c);
}
}
Related
Good day everyone! I am trying to create a desktop application using java swing wherein the user can upload pdf files to the mysql database. I already did the upload part in the application, but I'm having trouble on making a download button in the application. The function of the download button is to retrieve the pdf file in the mysql database and then download it in the user's computer.
here's what I found in inserting pdf file from https://www.java-tips.org/other-api-tips-100035/69-jdbc/845-how-to-storeretrieve-pdf-document-tofrom-sqlserver.html
The above link has already a function in getting pdf data, but I can't seem to understand how to implement it in my download button.
public void upload(Connection conn,String filename) {
int len;
String query;
PreparedStatement pstmt;
try {
File file = new File(filename);
FileInputStream fis = new FileInputStream(file);
len = (int)file.length();
query = ("insert into fileStorage VALUES(?,?,?)");
pstmt = conn.prepareStatement(query);
pstmt.setString(1,file.getName());
pstmt.setInt(2, len);
//method to insert a stream of bytes
pstmt.setBinaryStream(3, fis, len);
pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
What I'm having a trouble is making a function for my download button. how do I retrieve the file from database and download it at the same time after clicking the download button.
Yeah so unfortunately I don't know your table format however we should be able to create a prepared statement that gets the file raw bytes from the database. The following will get the byte array from the database and then create a new file, if necessary, from the raw bytes.
Change fileName to the proper name of the column for the file name.
Change fileContent to the name of the column for the byte array.
Make sure fileContent is a varbinary type.
Replace null in my reference to download(Connection, String) with a legitimate non-null Connection reference.
public static void main(String[] args) {
try {
byte[] download = download(null, "test");
Path output = Paths.get("my", "output", "file.pdf");
Files.write(output, download, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
} catch (IOException | SQLException e) {
throw new RuntimeException("Uh oh something went wrong!", e);
}
}
static byte[] download(Connection connection, String fileName) throws SQLException {
try (PreparedStatement statement = connection.prepareStatement("SELECT * FROM fileStore WHERE fileName = ?")) {
statement.setString(1, fileName);
try (ResultSet results = statement.getResultSet()) {
if (results.next()) {
return results.getBytes("fileContent");
}
}
}
throw new IllegalStateException("No file can be found for this name.");
}
I'm trying to store documents(doc,ppt,pdf,txt..etc) in MSSQL(server running in AWS). I'm working on the app module (android). I can get the files from the user but I'm not able to upload it to the database.
What I've done so far:
Tried to upload the file directly using setBinaryStream
Tried to upload the fileInputStream using setBinaryStream
No blob type can be declared in this database column
Update
Code Requested:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.sm_attachments:
FilePickerDialog filePickerDialog = new FilePickerDialog(SendMailToCustomers.this,properties);
filePickerDialog.setTitle("Select Files");
filePickerDialog.show();
filePickerDialog.setDialogSelectionListener(new DialogSelectionListener() {
#Override
public void onSelectedFilePaths(String[] files) {
for (String file : files) {
Uri uri = Uri.fromFile(new File(file));
try {
File file1 = new File(uri.getPath());
//InputStream inputStream = new FileInputStream(new File(uri.getPath()));
byte[] bytesArray = null;
bytesArray = new byte[(int) file1.length()];
FileInputStream fileInputStream = new FileInputStream(file1);
fileInputStream.read(bytesArray);
String sql = "INSERT INTO Storedata (FileName,MyFile) values (?,?)";
PreparedStatement statement = con.prepareStatement(sql);
statement.setString(1,"myNewFile");
//statement.setBinaryStream(2, /*inputStream*/fileInputStream,fileInputStream.available());
statement.setBytes(2, /*inputStream*/bytesArray);
int row = statement.executeUpdate();
if(row>0){
Toast.makeText(SendMailToCustomers.this, "The File was inserted Successfully", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onSelectedFilePaths: Inserted File Successfully");
}
else{
Toast.makeText(SendMailToCustomers.this, "Failed To Insert File", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onSelectedFilePaths: Failed To Insert File");
}
} catch (Exception e) {
Log.d(TAG, "onSelectedFilePaths: "+"Exception - "+e.getMessage()+"\n");
e.printStackTrace();
}
break;
The String[] files - are the selected files(Uri) for upload.
Next is the picture of my SQL Database:
MyFile is varbinary(MAX)
Upon doing this : statement.setBytes(2, /inputStream/bytesArray);
I get the below result. But this is around 433984 byte length i.e. bytes read for one file. How should i go about this?
The BULK IMPORT would not natively be able to do this however if you are on SQL2005 or greater you can use SSIS. The first step would be to perform an Exectute Process Task and use a zip utility to unzip the file. The second step is to use the SSIS Bulk Insert task to push the data into SQL Server.
I am trying to retrieve a zip from my database, but each time the generated zip is corrupted. The zip is supposed to contain 3 pdf files, but when I generate it, it only contains the first one with size 0 and when I try to open the zip "Unexpected end of archive" error popup is displayed. I cannot figure out what's wrong, as the file in the database is not corrupted and the code is working in my PC, and many other remote servers, but not on a specific remote server (all run on wildfly 10, same mysql database configuration, with the same zip stored in database). My code is the following (JDBC):
...
Statement stmt = conn.createStatement();
ResultSet rsstmt.executeQuery("SELECT document_data from table "
+ "WHERE condition");
if (rs.next() && rs.getBytes("document_data") != null) {
ByteArrayInputStream(rs.getBytes("document_data"));
File zipped= new File("exported.zip");
FileOutputStream fos = new FileOutputStream(zipped);
byte[] buffer = new byte[1];
InputStream is = rs.getBinaryStream(1);
while (is.read(buffer) > 0) {
fos.write(buffer);
}
fos.close();
}
I tried the following code too, but didn't work either:
InputStream in = null;//zip bytes
OutputStream out;//zip archive to be generated
.
.
.
if (rs.next() && rs.getBytes("document_data") != null) {
in = new ByteArrayInputStream(rs.getBytes("document_data"));
}
out = new FileOutputStream("exported.zip");
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
When executing the following SQL query, the zip generated is NOT corrupted:
SELECT document_data INTO DUMPFILE '/tmp/exported.zip' FROM table WHERE condition;
NOTE: The zip size in database(LONGBLOB field) is 830K.
NOTE: I tried with JDBC and Hibernate, but result is the same.
Any ideas on this strange behavior?
You are both calling getBytes(), which reads out the blob, and then reading from its input stream, which by this stage will be empty.
Get rid of the getBytes() call.
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 tried to uplad a pdf file using java.sql.PreparedStatement to mysql Blob field using the following code.
File inFile = new File("Path+BLOCK.pdf");
byte[] b = new byte[(int)inFile.length()];
PreparedStatement psmnt = (PreparedStatement)
con.prepareStatement("INSERT INTO
2012DOC (SRNO,DOCUMENT)
VALUES (?,?)"
); //con is java.sql.Connection object
psmnt.setString(1, "1200021");
psmnt.setBytes(2, b);
psmnt.executeUpdate();
This code executes without error and database shows blob content, but when I try to retrieve the file using the below code it gives a corrupt file which doesn't open.
ResultSet rs=con.Execute("SELECT DOCUMENT FROM 2012DOC");
rs.next();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=kjsahkjd.pdf");
java.sql.Blob blob = rs.getBlob("DOCUMENT");
ServletOutputStream servletOutputStream = response.getOutputStream();
InputStream in = blob.getBinaryStream();
int length = (int) blob.length();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
while ((length = in.read(buffer)) != -1) {
servletOutputStream.write(buffer, 0, length);
}
in.close();
servletOutputStream.flush();
servletOutputStream.close();
It outputs the file with same size as the original,but the file doesn't open.
The pdf reader is fired but cannot open the file and gives an error 'the file was either damaged or not supported file type'
Ahhh...After a little debugging I found the code that uploads is troublesome, and finally got the right way to do it.
Here is what I did...I'm posting it so that others with same problem can solve it
After Converting the java.io.File to java.io.FileInputStream
FileInputStream io = new FileInputStream(inFile);
Set the BLOB field using psmnt.setBinaryStream()
psmnt.setBinaryStream(3, (InputStream)io,(int)inFile.length());
remove " java.sql.Blob blob = rs.getBlob("DOCUMENT"); "
and don't initialize length i.e instead of
int length = (int) blob.length();
just write
int length;
then it downloads file successfully .. enjoy :)