ZipOutputStream.finish() and write file in a wrong directory and Tomcat - java

when i call .finish() and .close() for a zipOutputStream for download a zip file on a page of my webApp, it saves the content of zip file in my temp user folder ( example: c:/user/appdata/local/temp ) but i want to save this files in TomcatHome/temp.
// setting headers
response.setContentType("application/zip");
response.setStatus(HttpServletResponse.SC_OK);
response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\"");
// creating byteArray stream, make it bufforable and passing this buffor to ZipOutputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);
ZipOutputStream zipOutputStream = new ZipOutputStream(bufferedOutputStream);
for (int i = 0; i < listIdFile.size(); i++) {
try {
FileDTO file = this.fileDAO.getFileById(listIdFile.get(i));
File fileFull = this.fileDAO.readFileFull(Integer.parseInt(file.getId()));
zipOutputStream.putNextEntry(new ZipEntry(file.getNomeFile()));
FileInputStream fileInputStream = new FileInputStream(fileFull);
IOUtils.copy(fileInputStream, zipOutputStream);
fileInputStream.close();
zipOutputStream.closeEntry();
} catch (Exception e) {
log.error(e.getMessage());
e.printStackTrace();
// return downloadDocumentoDaLocale(response, listIdFile);
}
}
if (zipOutputStream != null) {
// zipOutputStream.finish();
zipOutputStream.close();
zipOutputStream.finish();
IOUtils.closeQuietly(zipOutputStream);
}
IOUtils.closeQuietly(bufferedOutputStream);
IOUtils.closeQuietly(byteArrayOutputStream);
}
Any suggest?
Thank you

Related

Creating zip using java and make it downloadable

I have this program which I am trying to use to create a zip file of the file located in the directory.
The program runs but in chrome it fails to download by saying the network error.
In Mozilla, it says Ut0ij4ld.ZIP.part could not be saved, because the source file could not be read.
what am I doing wrong, is there a better approach to do this?
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = "D:\\Test\\";
File directory = new File(path);
String[] files = directory.list();
//check if directories have files
if (files != null && files.length > 0) {
//create zip stream
byte[] zip = zipFiles(directory, files);
// Sends the response back to the user / browser with zip content
ServletOutputStream sos = response.getOutputStream();
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"DATA.ZIP\"");
sos.write(zip);
sos.flush();
}
request.setAttribute("DownloadMessage", "Successfully");
request.getRequestDispatcher("DownloadZipFile.jsp").forward(request, response);
}
private byte[] zipFiles(File directory, String[] files) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
byte bytes[] = new byte[4096];
for (String fileName : files) {
try (FileInputStream fis = new FileInputStream(directory.getPath()
+ "/" + fileName);
BufferedInputStream bis = new BufferedInputStream(fis)) {
zos.putNextEntry(new ZipEntry(fileName));
int bytesRead;
while ((bytesRead = bis.read(bytes)) != -1) {
zos.write(bytes, 0, bytesRead);
}
zos.closeEntry();
}
}
zos.flush();
baos.flush();
zos.close();
baos.close();
return baos.toByteArray();
}
This works,
#Override
protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//set the content type to zip
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"DATA.ZIP\"");
//to write it over http
ServletOutputStream ouputStream = response.getOutputStream();
//for writing files in the ZIP file format. Includes support for both compressed and uncompressed entries
ZipOutputStream zos= new ZipOutputStream(ouputStream);
//your file root folder
File rootFolder= new File ("D:\\Test\\") ;
// Looping through all the files
for (File file: rootFolder.listFiles()){
try {
writeToZip(zos,file);
} catch (Exception ex) {
Logger.getLogger(Zipper.class.getName()).log(Level.SEVERE, null, ex);
}
}
zos.close();
ouputStream.close();
}
private static void writeToZip(ZipOutputStream zos,File file) throws Exception{
FileInputStream fis=new FileInputStream(file);
ZipEntry zipEntry= new ZipEntry(file.getName());
zos.putNextEntry(zipEntry);
final byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
fis.close();
} }

Create text file and add to zip file and download spring boot with out savind in local server

create and download zip file by adding list of text files. with out creating the file in local server, it should be download at client side direct,
Here i added a code snippet, it was creating in local server, but i dont want that, it should create and download at client side instant. Please help me in this way..
#GetMapping("/download/rawdata")
public void downloadRawdata(#RequestParam("date") String date){
log.info("date : "+date);
List<Rawdata> rawdatas = rawdataRepoisotry.findRawdataByDate(date);
log.info("size of rawdata : "+rawdatas.size());
List<File> files = new ArrayList<File>();
int i = 1;
for(Rawdata rawdata : rawdatas){
log.info("rawdata : "+ rawdata.getRawdata());
File file = new File(i+".txt");
try (Writer writer = new BufferedWriter(new FileWriter(file))) {
String contents = rawdata.getRawdata();
writer.write(contents);
files.add(file);
} catch (IOException e) {
e.printStackTrace();
}
i++;
}
try {
zipFile(files, new File(date+".zip"));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Failed while creating Zip file");
}
}
public FileOutputStream zipFile(final List<File> files, final File targetZipFile) throws IOException {
try {
FileOutputStream fos = new FileOutputStream(targetZipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
byte[] buffer = new byte[128];
for(File currentFile : files){
if (!currentFile.isDirectory()) {
ZipEntry entry = new ZipEntry(currentFile.getName());
FileInputStream fis = new FileInputStream(currentFile);
zos.putNextEntry(entry);
int read = 0;
while ((read = fis.read(buffer)) != -1) {
zos.write(buffer, 0, read);
}
zos.closeEntry();
fis.close();
}
}
zos.close();
fos.close();
return fos;
} catch (FileNotFoundException e) {
System.out.println("File not found : " + e);
throw new FileNotFoundException();
}
}
Here is an example using FileSystemResource.
What has been modified is (see the numbers in the commented code ) :
1) Declare that the response will be of type application/octet-stream
2) #ResponseBody
Annotation that indicates a method return value should be bound to the
web response body
3) Declare that the method returns a FileSystemResource body
4) Return the FileSystemResource entity based on your created zip file
Note that this will still create the file on the server side first, but you may want to use File.createTempFile and File.deleteOnExit.
#GetMapping("/download/rawdata", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)//1
#ResponseBody //2
public ResponseEntity<FileSystemResource> downloadRawdata(#RequestParam("date") String date){ //3
log.info("date : "+date);
List<Rawdata> rawdatas = rawdataRepoisotry.findRawdataByDate(date);
log.info("size of rawdata : "+rawdatas.size());
List<File> files = new ArrayList<File>();
int i = 1;
for(Rawdata rawdata : rawdatas){
log.info("rawdata : "+ rawdata.getRawdata());
File file = new File(i+".txt");
try (Writer writer = new BufferedWriter(new FileWriter(file))) {
String contents = rawdata.getRawdata();
writer.write(contents);
files.add(file);
} catch (IOException e) {
e.printStackTrace();
}
i++;
}
try {
File resultFile = new File(date+".zip");
zipFile(files, resultFile);
return new ResponseEntity<>(new FileSystemResource(resultFile), HttpStatus.OK); //4
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Failed while creating Zip file");
}
}

Spring REST - Damaged/Blank File being downloaded

I am trying to create a endpoint to render/serve PDF file.
I have gone through the following links to build the API, but still facing some issues.
link 1
link 2
Following is my code :
byte[] targetArray = null;
InputStream is = null;
InputStream objectData = object.getObjectContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(objectData));
char[] charArray = new char[8 * 1024];
StringBuilder builder = new StringBuilder();
int numCharsRead;
while ((numCharsRead = reader.read(charArray, 0, charArray.length)) != -1) {
builder.append(charArray, 0, numCharsRead);
}
reader.close();
objectData.close();
object.close();
targetArray = builder.toString().getBytes();
is = new ByteArrayInputStream(targetArray);
return ResponseEntity.ok().contentLength(targetArray.length).contentType(MediaType.APPLICATION_PDF)
.cacheControl(CacheControl.noCache()).header("Content-Disposition", "attachment; filename=" + "testing.pdf")
.body(new InputStreamResource(is));
When I hit my API using postman, I am able to download PDF file but the problem is it is totally blank. What might be the issue ?
There are multiple ways to download files from server, you can use ResponseEntity<InputStreamResource>, HttpServletResponse.Below are the two methods to download.
#GetMapping("/download1")
public ResponseEntity<InputStreamResource> downloadFile1() throws IOException {
File file = new File(FILE_PATH);
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=" + file.getName())
.contentType(MediaType.APPLICATION_PDF).contentLength(file.length())
.body(resource);
}
OR
You can use StreamingResponseBody to download large files. In this case server writes data to OutputStream at same time Browser read data which means its parallel.
#RequestMapping(value = "downloadFile", method = RequestMethod.GET)
public StreamingResponseBody getSteamingFile(HttpServletResponse response) throws IOException {
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"demo.pdf\"");
InputStream inputStream = new FileInputStream(new File("C:\\demo-file.pdf"));
return outputStream -> {
int nRead;
byte[] data = new byte[1024];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
System.out.println("Writing some bytes..");
outputStream.write(data, 0, nRead);
}
};
}
You can try to use apache commons IOUtils. Why reinvent wheel :)
1. Open a connection to remote server
2. Copy the inputStream to the destination file outputStream.
public void downloadFileFromRemoteLocation(String serverlocation, File destinationFile) throws IOException
{
try (FileOutputStream fos = new FileOutputStream( destinationFile )){
URL url = new URL(serverlocation);
URLConnection connection = url.openConnection();
IOUtils.copy( connection.getInputStream(), fos);
}
}
if you want to stick to just Java then look at snippet below
try {
// Get the directory and iterate them to get file by file...
File file = new File(fileName);
if (!file.exists()) {
context.addMessage(new ErrorMessage("msg.file.notdownloaded"));
context.setForwardName("failure");
} else {
response.setContentType("APPLICATION/DOWNLOAD");
response.setHeader("Content-Disposition", "attachment"+
"filename=" + file.getName());
stream = new FileInputStream(file);
response.setContentLength(stream.available());
OutputStream os = response.getOutputStream();
os.close();
response.flushBuffer();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

java zip archive damaged

I have a problem with a created archive - when trying to unzip windows shows that there's an error. Is it an issue with code?
File dir = new File("M:\\SPOT/netbeanstest/TEST/PDF");
String archiveName = "test.zip";
byte[] buf = new byte[1024];
try {
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(
archiveName));
for (String s : dir.list()) {
File toCompress = new File(dir, s);
FileInputStream fis = new FileInputStream(toCompress);
zos.putNextEntry(new ZipEntry(s));
int len;
while((len = fis.read(buf))>0){
zos.write(buf, 0, len);
}
zos.closeEntry();
fis.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I'll write write my comment down as an answer because it solved the problem.
All streams (InputStream, OutputStream) should be closed with their close() method to make sure that the data has been written out and no open handlers has left over.
It's a good idea to do it in a finally block, like this:
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(archiveName));
try {
for (String s : dir.list()) {
File toCompress = new File(dir, s);
FileInputStream fis = new FileInputStream(toCompress);
try {
zos.putNextEntry(new ZipEntry(s));
int len;
while((len = fis.read(buf))>0){
zos.write(buf, 0, len);
}
zos.closeEntry();
} finally {
fis.close();
}
}
} finally {
zos.close();
}

What is the "Jodatime" / "Apache commons" of Zip/Unzip Java utilities?

I'm sure that there is a mature, widely used ZIP file utility out there, I just can't seem to find out. Something with the same maturity as Apache Commons, Google Collections, Joda Time
I'm trying to do the simplest task of getting a zip file as a byte array (ZipInputStream) and extract it to a folder. this seems like a very tedious task.
I would hope for a syntactic sugar API that does somethnig like this:
public class MyDreamZIPUtils
public static void extractToFolder(ZipInputStream zin, File outputFolderRoot){
...
}
public static void extractToFolder(ZipFile zf, File outputFolderRoot){
...
}
public static zipFolder(File folderToZip, File zippedFileLocation){
...
}
public static zipFolder(File folderToZip, ByteArrayOutputStream zipResult){
...
}
Anything like this?
Am I missing something?
http://commons.apache.org/compress/
I am sure you can write the "syntactic sugar" on top of that.
Javadoc: http://commons.apache.org/compress/apidocs/index.html
I used only Java API calls... I did not do all your methods. you can figure them out from here... Please note i do not claim that the code is bug free... use at your own risk :)
public static void extractToFolder(ZipInputStream zin, File outputFolderRoot)
throws IOException {
FileOutputStream fos = null;
byte[] buf = new byte[1024];
ZipEntry zipentry;
for (zipentry = zin.getNextEntry(); zipentry != null; zipentry = zin.getNextEntry()) {
try {
String entryName = zipentry.getName();
System.out.println("Extracting: " + entryName);
int n;
File newFile = new File(outputFolderRoot, entryName);
if (zipentry.isDirectory()) {
newFile.mkdirs();
continue;
} else {
newFile.getParentFile().mkdirs();
newFile.createNewFile();
}
fos = new FileOutputStream(newFile);
while ((n = zin.read(buf, 0, 1024)) > -1)
fos.write(buf, 0, n);
fos.close();
zin.closeEntry();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null)
try {
fos.close();
} catch (Exception ignore) {
}
}
}
zin.close();
}
public static void zipFolder(File folderToZip, File zippedFileLocation) throws IOException {
// create a ZipOutputStream to zip the data to
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zippedFileLocation));
String path = "";
zipDir(folderToZip, zos, path);
// close the stream
zos.close();
}
private static void zipDir(File directory, ZipOutputStream zos, String path) throws IOException {
File zipDir = directory;
// get a listing of the directory content
String[] dirList = zipDir.list();
byte[] readBuffer = new byte[2156];
int bytesIn = 0;
// loop through dirList, and zip the files
for (int i = 0; i < dirList.length; i++) {
File f = new File(zipDir, dirList[i]);
if (f.isDirectory()) {
zipDir(new File(f.getPath()), zos, path + f.getName() + "/");
continue;
}
FileInputStream fis = new FileInputStream(f);
try {
ZipEntry anEntry = new ZipEntry(path + f.getName());
zos.putNextEntry(anEntry);
bytesIn = fis.read(readBuffer);
while (bytesIn != -1) {
zos.write(readBuffer, 0, bytesIn);
bytesIn = fis.read(readBuffer);
}
} finally {
fis.close();
}
}
}
Reference Java2s

Categories