Downloading BLOB file has no data - java

I'm trying to download BLOB data from MySQL, but all I can get is a file with 1 KB size.
I've got a table which contains checkboxes, and I'm looking for the checked ones. The values are the IDs.
This is the code:
public class FileDownloadServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
DBConnection DBC = new DBConnection();
Connection con = DBC.connection();
String[] checkBoxValues = request.getParameterValues("files");
for (int i = 0; i < checkBoxValues.length; i++) {
String fileDL = "select * from uploads where file_id='"+checkBoxValues[i]+"'";
try {
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(fileDL);
while(rs.next()){
String fileName = rs.getString("file_name");
Blob blob = rs.getBlob("file");
InputStream input = blob.getBinaryStream();
int fileSize = (int) blob.length();
System.out.println(fileSize);
ServletContext context = getServletContext();
String mimeType = context.getMimeType(fileName);
if (mimeType == null) {
mimeType = "application/octet-stream";
}
response.setContentType(mimeType);
response.setContentLength(fileSize);
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", fileName);
response.setHeader(headerKey, headerValue);
OutputStream output = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
input.close();
output.close();
}
} catch (SQLException ex) {
Logger.getLogger(FileDownloadServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
I have no idea where I went wrong. Thanks in advance!

output.write(buffer, 0, bytesRead)
always uses the same offset. You are never really advancing in your resulting stream. You'd have to increment your offset by bytesRead
EDIT: Explanation
You are using https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#write%28byte[],%20int,%20int%29
This method writes the bytes in your buffer to the outputstream, starting at position 0.
Now, in the next iteration, you read the next 4k bytes and again write it to the outputstream. But your offset hasn't changed, so you are not appending the new buffer-content but overwriting the previsously written bytes, because you said to write from position 0 again. Therefor, you need to advance the offset by the same amount of bytes you have previously written.
EDIT: Spoiler
So here's the spoiler:
int bytesRead = -1;
int offset = 0;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, offset, bytesRead);
offset += bytesRead;
}
Not tested.
Additionally, why do you want to write in 4k chunks?
Why not just
byte[] buffer = new byte[1];
while (input.read(buffer) > 0) {
output.write(buffer);
}

Related

How to get BufferedInputStream from Multipart?

I'm trying to get a BufferedInputStream from an uploaded cvs file.
I'm working with a Multipart derived from the cvs file.
When I first get the Multipart, it's a BufferedInputStream, but the buffer is all null.
But if I look deeper down, there's another buffer in the CoyoteInputStream and that has data.
How can I get at this second buffer? My code is below.
And of course it's throwing a null exception when it gets to
while ((multiPartDataPos = stream.read(buffer)) >= 0)
What am I doing wrong? Am I mistaken that the CoyoteInputStream is the data I want?
public byte[] handleUploadedFile(Multipart multiPart) throws EOFException {
Multipart multiPartData = null;
BufferedInputStream stream = null;
int basicBufferSize = 0x2000;
byte[] buffer = new byte[basicBufferSize];
int bufferPos = 0;
try {
while (multiPart.hasNext()) {
int multiPartDataPos = bufferPos;
multiPartData = (Multipart) multiPart.next();
stream = new BufferedInputStream(multiPartData.getInputStream());
while ((multiPartDataPos = stream.read(buffer)) >= 0) {
int len = stream.read(buffer, multiPartDataPos, buffer.length - multiPartDataPos);
multiPartDataPos += len;
}
bufferPos = bufferPos + multiPartDataPos;
}
} ...
Your code doesn't make any sense.
while ((multiPartDataPos = stream.read(buffer)) >= 0) {
At this point you have read multiPartDataPos bytes into buffer, so that buffer[0..multiPartDataPos-1] contains the data just read.
int len = stream.read(buffer, multiPartDataPos, buffer.length - multiPartDataPos);
At this point you are doing another read, which could return -1, which will otherwise add some data from multiPartPos to multiPartDataPos+len-.
multiPartDataPos += len;
This step is only valid if len > 0.
And you are doing nothing with the buffer; and next time around the loop you will clobber whatever you just read.
The correct way to read any stream in Java is as follows:
while ((count = in.read(buffer)) > 0)
{
// use buffer[9..count-1], for example out.write(buffer, 0, count);
}
I don't understand why you think access to an underlying stream is required or what it's going to give you that you don't already have.
Turns out the better solution was to use move the data from an InputStream to a ByteArrayOutputStream and then return ByteArrayOutputStream.toByteArray()
Multipart multiPartData = null;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read;
byte[] input = new byte[4096];
InputStream is;
try {
multiPartData = (Multipart)multipart.next();
is = multiPartData.getInputStream();
while ((read = is.read(input, 0, input.length)) != -1) {
buffer.write(input, 0, read);
}
buffer.flush();
return buffer.toByteArray(); // just a test right now
}

Upload Image to FTP Server using ADF Mobile Application

I want to upload an image to FTP Server. Currently i am using JDeveloper 12c(12.1.3.0).
My Code:
private static final int BUFFER_SIZE = 4096;
public String fileUploadMethod(String imagePath){
String ftpUrl = "ftp://";
String host = "http://192.168.0.42";
String user = "XXXXXX";
String pass = "XXXXXX";
String filePath = "783771-1.jpg";
String uploadPath = imagePath;
ftpUrl =ftpUrl + user +":"+ pass+"#"+host+"/"+filePath+";";
System.out.println("Upload URL: " + ftpUrl);
try {
URL url = new URL(ftpUrl);
URLConnection conn = url.openConnection();
OutputStream outputStream = conn.getOutputStream();
FileInputStream inputStream = new FileInputStream(uploadPath);
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outputStream.close();
System.out.println("File uploaded");
return "File uploaded";
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
I am getting an error MalFormedURLException i.e. in detail message "unknown protocol:ftp"
Is there any other option to upload an image using JDeveloper.
Any idea regarding this.
Thanks, Siddharth
Your ftpUrl is wrong. Remove http:// in the host variable. Should be ok then
I haven't really tried ftp upload. But I had tried with multipart form upload. As far as I know, MAF doesnt provide Out-Of-Box support for file upload. What I did was essential recreating the HTTP stream for the image upload.
The POC code is attached below. This may be definitely the CRUDEST implementation but I am not sure if there is a better way.
public void doUpload() {
try {
DeviceManager dm = DeviceManagerFactory.getDeviceManager();
String imgData =
dm.getPicture(50, DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URI, DeviceManager.CAMERA_SOURCETYPE_CAMERA,
false, DeviceManager.CAMERA_ENCODINGTYPE_PNG, 0, 0);
imgData = imgData.substring(7, imgData.length());
int start = imgData.lastIndexOf('/');
String fileName = imgData.substring(start+1, imgData.length());
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
String requestMethod = RestServiceAdapter.REQUEST_TYPE_POST;
String requestEndPoint = restServiceAdapter.getConnectionEndPoint("serverBaseUrl");
String requestURI = "/workers/100000018080264";
String request = requestEndPoint + requestURI;
HashMap httpHeadersValue = new HashMap();
httpHeadersValue.put("X-ANTICSRF", "TRUE");
httpHeadersValue.put("Connection", "Keep-Alive");
httpHeadersValue.put("content-type","multipart/form-data; boundary=----------------------------4abf1aa47e18");
// Get the connection
HttpConnection connection = restServiceAdapter.getHttpConnection(requestMethod, request, httpHeadersValue);
OutputStream os = connection.openOutputStream();
byte byteBuffer[] = new byte[50];
int len;
//String temp is appended before the image body
String temp = "------------------------------4abf1aa47e18\r\nContent-Disposition: form-data; name=\"file\"; filename=\"" +fileName+ "\"\r\nContent-Type: image/jpeg\r\n\r\n";
InputStream stream = new ByteArrayInputStream(temp.getBytes("UTF-8"));
if (stream != null) {
while ((len = stream.read(byteBuffer)) >= 0) {
os.write(byteBuffer, 0, len);
}
stream.close();
}
FileInputStream in = new FileInputStream(imgData);
if (in != null) {
while ((len = in.read(byteBuffer)) >= 0) {
os.write(byteBuffer, 0, len);
}
in.close();
}
//The below String is appended after the image body
InputStream stream2 =new ByteArrayInputStream("\r\n------------------------------4abf1aa47e18--\r\n".getBytes("UTF-8"));
if (stream2 != null) {
while ((len = stream2.read(byteBuffer)) >= 0) {
os.write(byteBuffer, 0, len);
}
stream2.close();
}
int status = connection.getResponseCode();
InputStream inputStream = restServiceAdapter.getInputStream(connection);
ByteArrayOutputStream incomingBytes = new ByteArrayOutputStream() // get and process the response.
while ((len = inputStream.read(byteBuffer)) >= 0) {
incomingBytes.write(byteBuffer, 0, len);
}
String ret = incomingBytes.toString();
incomingBytes.close();
} catch (Exception e) {
e.printStackTrace();
}
}

Unable to upload file with jersey

I am using this webservice to upload a file using jersey
public class upload {
#POST
#Path(value = "upload")
#Consumes("image/jpg")
public Response uploadPng(File file) throws IOException {
file = new File("C:/Users/Marwa/Desktop/Capture.jpg");
String uploadedFileLocation = "C:/Users/Desktop/" + file.getName();
DataInputStream diStream =new DataInputStream(new FileInputStream(file));
long len = (int) file.length();
byte[] fileBytes = new byte[(int) len];
int read = 0;
int numRead = 0;
while (read < fileBytes.length && (numRead =diStream.read(fileBytes, read,fileBytes.length - read)) >= 0) {
read = read + numRead;
}
// save it
writeToFile(diStream, uploadedFileLocation);
System.out.println("File uploaded to : " + uploadedFileLocation);
return Response.status(200).entity(file).build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream,String uploadedFileLocation) {
try {
OutputStream out =new FileOutputStream(new File(uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();}}}
When I execute my code i get a 405 error !!
Are there any suggestions to this issue?
public Response uploadPng(FormDataMultiPart multiPart) throws IOException {
You should pass the FormDataMultiPart parameter in the method which you are calling while uploading file.
Not sure if this is perfect solution. But solved similar problem by following approach.
First thing, you should use
public Response uploadPng(FormDataMultiPart multiPart) throws IOException {
Next to avoid 405 error add
#Produces(MediaType.TEXT_PLAIN)
above uploadpng method.

How to return and delete file?

I want to return file (read or load) from method and then remove this file.
public File method() {
File f = loadFile();
f.delete();
return f;
}
But when I delete a file, I delete it from disk and then exists only descriptor to non-existing file on return statement. So what is the most effective way for it.
You can't keep the File handle of deleted file, rather you can keep the data in a byte array temporarily, delete the file and then return the byte array
public byte[] method() {
File f =loadFile();
FileInputStream fis = new FileInputStream(f);
byte[] data = new byte[fis.available()];
fis.read(data);
f.delete();
return data;
}
// Edit Aproach 2
FileInputStream input = new FileInputStream(f);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int bytesRead = input.read(buf);
while (bytesRead != -1) {
baos.write(buf, 0, bytesRead);
bytesRead = input.read(buf);
}
baos.flush();
byte[] bytes = baos.toByteArray();
you can construct the file data from byte array
However, my suggestion is to use IOUtils.toByteArray(InputStream input) from Jakarta commons, why do you want re write when already in plate
Assuming you want to return the file to the browser, this is how I did it :
File pdf = new File("file.pdf");
if (pdf.exists()) {
try {
InputStream inputStream = new FileInputStream(pdf);
httpServletResponse.setContentType("application/pdf");
httpServletResponse.addHeader("content-disposition", "inline;filename=file.pdf");
copy(inputStream, httpServletResponse.getOutputStream());
inputStream.close();
pdf.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
private static int copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[512];
int count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}

Java openConnection calculate progress

I have the following method from which i am trying to update a progressBar as to how far the download has progressed:
private void wget(java.net.URL url, String destination) throws MalformedURLException, IOException {
java.net.URLConnection conn = url.openConnection();
java.io.InputStream in = conn.getInputStream();
File dstfile = new File(destination);
OutputStream out = new FileOutputStream(dstfile);
byte[] buffer = new byte[512];
int length;
int readBytes = 0;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
// Get progress
int contentLength = conn.getContentLength();
if (contentLength != -1) {
//System.out.println((length / contentLength) * 100); ??
UpdateForm.progressBar.setValue(2);
} else {
}
}
in.close();
out.close();
}
However i cannot seem to figure out how to calculate how many % have gone..
Any ideas?

Categories

Resources