Dynamically stream files into a zip file response - java

I'm trying to dynamically zip my files as a response for the user, but for some reason they become slightly corrupted on the way. The client can receive them, open the zip folder and browse the files. However, opening or extracting them won't work.
Here's my code:
private void dynamicallyZipFiles(IHTTPSession session) {
try {
// Let's send the headers first
OutputStream os = session.getOutputStream();
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os, "UTF-8")), false);
pw.append("HTTP/1.1 200 \r\n");
printHeader(pw, "Connection", "keep-alive");
printHeader(pw, "Content-Type", "application/zip, application/octet-stream");
printHeader(pw, "Content-Disposition", "attachment; filename=\"pack.zip\"");
printHeader(pw, "Transfer-Encoding", "chunked");
pw.append("\r\n");
pw.flush();
// Send all the files from the list of files
ChunkedOutputStream cos = new ChunkedOutputStream(os);
ZipOutputStream zos = new ZipOutputStream(cos);
final LinkedList<String> files = new LinkedList<String>();
files.add("file1.txt");
files.add("file2.txt");
while (!files.isEmpty()) {
String file = files.remove();
File toBeSent = new File(file);
try {
ZipEntry ze = new ZipEntry(file);
zos.putNextEntry(ze);
InputStream is = (InputStream) new FileInputStream(toBeSent);
long BUFFER_SIZE = 16 * 1024;
byte[] buff = new byte[(int) BUFFER_SIZE];
int len;
while ((len = is.read(buff)) > 0) {
zos.write(buff, 0, len);
}
is.close();
zos.flush();
cos.flush();
zos.closeEntry();
} catch (Exception e) {
e.printStackTrace();
}
}
// Files have been sent, send the closing chunk
//cos.write("0\r\n\r\n".getBytes(), 0, "0\r\n\r\n".getBytes().length);
// The above line of code was the problem! Without it, it works!
cos.flush();
zos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// Helper for printing headers
private void printHeader(PrintWriter pw, String key, String value) {
pw.append(key).append(": ").append(value).append("\r\n");
}
I've been struggling for quite some hours already with this. I believe it has to have something to do with the closing chunk or with the closing of the connection?
I'm not sure what's the right order or way to close streams. I believe that when you have kind of "layered" streams and you close the top most one it will automatically close all the ones below too? And how about flush, if you flush a stream, will it flush the streams below it as well?With this I mean that my ZipStream for example, if I close it, will it close all the other streams as well? And if I flush it, will it flush all the other streams as well again?

Related

zip,move and size of file which is in a server path using java

I have a file in the server, I want to create three java APIs, which will do the below three operations in dependently.
Get the file size
Move a file with different file name to a different server location
Zip the file
In my existing code we are executing Linux commands to perform those operations, unfortunately, Linux commands are not getting executed, this is due to some server/set up issue, so I am forced to use Java commands.(We use JDK 1.6)
I am not a Java developer. I have gone through some of the previously answered questions, but they are not explaining about file in server path. Any help is much appreciated.
To get the file size in bytes:
File file = new File("filename.txt");
long fileSize = file.length();
To move a file you must first copy it and then delete the original:
InputStream inStream = null;
OutputStream outStream = null;
try {
File fromFile = new File("startfolder\\filename.txt");
File toFile = new File("endfolder\\filename.txt");
inStream = new FileInputStream(fromFile);
outStream = new FileOutputStream(toFile);
byte[] buffer = new byte[1024];
int length;
while ((length = inStream.read(buffer)) > 0){
outStream.write(buffer, 0, length);
}
inStream.close();
outStream.close();
fromFile.delete();
} catch(IOException e) {
e.printStackTrace();
}
To zip a file:
byte[] buffer = new byte[1024];
try {
FileInputStream fileToZip = new FileInputStream("filename.txt");
FileOutputStream fileOutputStream = new FileOutputStream("filename.zip");
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
ZipEntry zipEntry= new ZipEntry("filename.txt");
zipOutputStream.putNextEntry(zipEntry);
int len;
while ((len = fileToZip.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
fileToZip.close();
zipOutputStream.closeEntry();
zipOutputStream.close();
} catch(IOException e) {
e.printStackTrace();
}

Java - Converting data handler to file is time consuming

I need to send the audio file the from client to the server. So I have a REST API for which the attachment is the input. I need to convert this attachment to audio file in the Java layer. I tried two different ways but both are time consuming. Any suggestions?
Method1:
File tempFile=File.createTempFile("tempFile", ".wav");
tempFile.deleteOnExit();
DataHandler handler = attachemnt.getDataHandler();
InputStream Filestream = handler.getInputStream();
if (Filestream.available()>10) {
OutputStream out = new FileOutputStream(tempFile);
byte[] buf = new byte[1024];
int len;
while ((len = Filestream.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
Filestream.close();
}
Method2:
File tempFile=File.createTempFile("tempFile", ".wav");
tempFile.deleteOnExit();
DataHandler handler = attachment.getDataHandler();
InputStream is = handler.getInputStream();
if (is.available() > 10) {
OutputStream os = new FileOutputStream(tempFile);
// This will copy the file from the two streams
IOUtils.copy(is, os);
// This will close two streams catching exception
IOUtils.closeQuietly(os);
IOUtils.closeQuietly(is);
}

Client Server File transfer Chat Java GUI

i have a client and a server,
1) client should send choose files and send them to server
2) client should send a command message so that the server knows that the incoming is a file not a message (thats why i have "SF" which stands for send file)
3) server receives files and store them somewhere in the system
Also, i dont want to close the socket after i send/receive files (because this is done when the client clicks on disconnect button)
Below is my code but it does not work for some reason, if someone can help me fix it.
Client
public void sendFiles(String file) {
this.out.print("SF");
this.out.flush();
File myfile = new File(file);
// Get the size of the file
long length = myfile.length();
if (length > Integer.MAX_VALUE) {
System.out.println("File is too large.");
}
byte[] bytes = new byte[(int) length];
FileInputStream fis;
try {
fis = new FileInputStream(myfile);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream());
int count;
while ((count = bis.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
System.out.println("count "+bytes.length);
// this.out.flush();
out.flush();
// out.close();
fis.close();
bis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Server
public void recvFile() {
InputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
int bufferSize = 0;
try {
is = sock.getInputStream();
bufferSize = sock.getReceiveBufferSize();
System.out.println("Buffer size: " + bufferSize);
fos = new FileOutputStream("/Users/day/Documents/Parallels/server.txt");
bos = new BufferedOutputStream(fos);
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
}
System.out.println("bytes "+bytes.length);
System.out.println("count "+count);
bos.flush();
bos.close();
// is.close();
// sock.close();
} catch (IOException e) {
System.out.println("ERROR" +e);
}
Also in the server side; this is how i jump to the method recvFile();
if (message.contains("SF")) {
recvFile();
}
MORE explanation about my problem:
It does not work in a sense that i dont know if the file is actually sent properly? or the file received properly because i get 0 bytes in the received file. Also, this is the thing i dont want to close the connection because this is a chat so how can i let the server know that this is the end of file?
Can someone help me making the code works because i dont know whats wrong? thanks
Could you kindly elaborate on the error that you are getting. That may help in answering. Because, prima facie the code structure looks fine.
Additionally, I presume that you are using TCP connection for file transfer.
P.S.: I couldn't add a comment to the question, so asking question here.

java client server chat transferred files not received properly

I have my client server chat
Client sends files and server receives them. But, the problem is that, i don't think that files are received properly because when i check the size of the files i see the difference is halfed for some reasons!
I am using GUI to browse for files in the client side, and then i'm sending a command to the server to know that the client is sending a file. But it is not working
Here is the client and server
public void sendFiles(String file) {
try {
BufferedOutputStream outToClient = null;
outToClient = new BufferedOutputStream(sock.getOutputStream());
System.out.println("Sending file...");
if (outToClient != null) {
File myFile = new File( file );
byte[] mybytearray = new byte[(int) myFile.length()];
FileInputStream fis = null;
fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
this.out.println("SF");
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
this.out.flush();
outToClient.flush();
outToClient.close();
System.out.println("File sent!");
return;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Server
public void recvFile() {
try {
byte[] aByte = new byte[1];
int bytesRead;
InputStream is = null;
is = sock.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (is != null) {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream("/Users/Documents/Received.png");
bos = new BufferedOutputStream(fos);
bytesRead = is.read(aByte, 0, aByte.length);
do {
baos.write(aByte);
bytesRead = is.read(aByte);
} while (bytesRead != -1);
bos.write(baos.toByteArray());
bos.flush();
bos.close();
// clientSocket.close();
} catch (IOException ex) {
// Do exception handling
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Can someone help me with this issue? As i don't know how to properly send and receive files
Thank you
You are using two copy techniques, and they are both wrong.
First:
byte[] mybytearray = new byte[(int) myFile.length()];
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
Here you are assuming:
That the file fits into memory.
That the file length fits into an int.
That read() fills the buffer.
None of these assumptions is valid.
Second:
byte[] aByte = new byte[1];
bytesRead = is.read(aByte, 0, aByte.length);
do {
baos.write(aByte);
bytesRead = is.read(aByte);
} while (bytesRead != -1);
Here you are:
Using a ridiculously small buffer of one byte.
Writing an extra byte if the file length is zero.
Using a do/while where the situation naturally calls for a while (as 99.99% of situations do), and therefore:
Using two read() calls, and only correctly checking the result of one of them.
Pointlessly using a ByteArrayOutputStream, which, as above, assumes the file fits into memory and that its size fits into an int. It also pointlessly adds latency.
Throw them both away and use this, at both ends:
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
where:
in is a FileInputStream in the case of sending the file, or the socket input stream in the case of receiving the file.
out is a FileOutputStream in the case of receiving the file, or the socket output stream in the case of sending the file

fast java Input\Output Stream

i have a servlet that copies a pdf file to the client using response output stream
private boolean copyStreamToStream(InputStream in, OutputStream target) {
logger.info("start copy file to stream");
try {
byte[] buffer = new byte[1024 * 8];
int len = in.read(buffer);
while (len != -1) {
target.write(buffer, 0, len);
len = in.read(buffer);
}
in.close();
target.flush();
target.close();
logger.info("end copy file to stream");
} catch (Exception ex) {
logger.error("Error: ", ex);
return false;
}
return true;
}
the InputStream for the pdf file on disk and OutputStream for response.getOutputStream()
the problem is that the PDF file is a big file and it takes a very long time to load it on client is there is any way to speed it up???
Send the file for download instead of passing it back as direct response object.
// Set the headers.
response.setContentType("application/x-download");
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
// Send the file for download.
OutputStream out = response.getOutputStream( );
Edited.

Categories