I am currently working on JAX-RS, where I'm trying to send and receive Zip files. Currently for sending the zip file in response, I'm able to achieve it using the below code (verified the zip downloading by entering the URL in the browser), but I'm not clear about writing the code logic to read the Zip file from response.
Please help me to achieve this functionality.
#GET
#Produces({"application/zip"})
#Path("getProduct")
public Response getProduct() {
String METHODNAME = "getProduct";
if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {
LOGGER.entering(CLASSNAME, METHODNAME);
}
File file;
try {
Properties prop = getProp();
file = new File(prop.getProperty("ZipLocation")+prop.getProperty("ProductZip"));
byte[] buffer = new byte[5120];
FileOutputStream fos = new FileOutputStream(file);
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze= new ZipEntry(prop.getProperty("ProductOutfile"));
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream("C:\\Documents\\ProductExtract.xml");
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
in.close();
zos.closeEntry();
zos.close();
} catch (FileNotFoundException ex) {
LOGGER.logp(Level.SEVERE, CLASSNAME, METHODNAME, ex.getMessage(), ex);
return Response.status(204).entity(ex.getMessage()).build();
} catch (Exception ex) {
LOGGER.logp(Level.SEVERE, CLASSNAME, METHODNAME, ex.getMessage(), ex);
return Response.status(204).entity(ex.getMessage()).build();
}
return Response.ok(file, "application/zip").header("Content-Disposition", "attachment; filename=\""+file.getName()+"\"")
.header("Content-Type", "application/zip").header("Set-Cookie", "fileDownload=true; path=/").build();
}
Kindly let me know how can I achieve reading the zip file from response of the above code.
Once you are using the JAX-RS Client API, your client code can be like:
Client client = ClientBuilder.newClient();
InputStream is = client.target("http://localhost:8080")
.path("api").path("getProduct")
.request().accept("application/zip")
.get(InputStream.class);
ZipInputStream zis = new ZipInputStream(is);
Then read the content of the ZipInputStream.
Related
I`m trying to compress a list of Xml converted on Strings, save them in only one zip file and returning as a body of a POST on restful. But everytime I save the file I get the error "The archive is either in unknown format or damaged".
protected ByteArrayOutputStream zip(Map<String, String> mapConvertedXml) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
try {
for(Map.Entry<String, String> current : mapConvertedXml.entrySet()){
ZipEntry entry = new ZipEntry(current.getKey() + ".xml");
entry.setSize(current.getValue().length());
zos.putNextEntry(entry);
zos.write(current.getValue().getBytes());
zos.flush();
}
zos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return baos;
}
Can anyone help me with that?
To test your zip file please save it temporarily in your filesystem and open it manualy.
FileOutputStream fos = new FileOutputStream(pathToZipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
Then, you can use something like that to construct your Rest Server and return your file.
public static Response getFileLast(#Context UriInfo ui, #Context HttpHeaders hh) {
Response response = null;
byte[] sucess = null;
ByteArrayOutputStream baos = getYourFile();
sucess = baos.toByteArray();
if(sucess!=null) {
response = Response.ok(sucess, MediaType.APPLICATION_OCTET_STREAM).header("content-disposition","attachment; filename = YourFileName").build();
} else {
response = Response.status(Status.NOT_FOUND).type(MediaType.APPLICATION_JSON).entity(new Error("Error downloading file.")).build();
}
return response;
}
You can test this Advanced Rest Client for example.
I want to create an Excel file from a method in Java and download it in a browser.
I have found an example on this post where you create the Excel file, but I want to create the .xls file and download it from a web browser.
How can I do that?
I finally found a solution for my problem...!!
This is working for me:
#RequestMapping("/downloadFile")
public void downloadFile(HttpServletRequest request, HttpServletResponse response) {
try {
String fileName = "C:/excelFile.xls";
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("firstSheet");
HSSFRow rowhead = sheet.createRow((short) 0);
rowhead.createCell(0).setCellValue("No.");
rowhead.createCell(1).setCellValue("Name");
rowhead.createCell(2).setCellValue("Address");
rowhead.createCell(3).setCellValue("Email");
HSSFRow row = sheet.createRow((short) 1);
row.createCell(0).setCellValue("1");
row.createCell(1).setCellValue("Carlos");
row.createCell(2).setCellValue("Costa Rica");
row.createCell(3).setCellValue("myNameh#gmail.com");
FileOutputStream fileOut = new FileOutputStream(fileName);
workbook.write(fileOut);
fileOut.close();
System.out.println("Your excel file has been generated!");
//Code to download
File fileToDownload = new File(fileName);
InputStream in = new FileInputStream(fileToDownload);
// Gets MIME type of the file
String mimeType = new MimetypesFileTypeMap().getContentType(fileName);
if (mimeType == null) {
// Set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
System.out.println("MIME type: " + mimeType);
// Modifies response
response.setContentType(mimeType);
response.setContentLength((int) fileToDownload.length());
// Forces download
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", fileToDownload.getName());
response.setHeader(headerKey, headerValue);
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = in.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
in.close();
outStream.close();
System.out.println("File downloaded at client successfully");
} catch (Exception ex) {
System.out.println(ex);
}
}
If you want to trigger a Java process from a Web Browser (HTTP request), then you need an application server (like Tomcat) to accept your HTTP request and execute some server-side code (Servlet). A main method like in the example cannot be launched by a HTTP request. Look here if you never wrote a Servlet before.
This has nothing to do with Excel, but this post shows how to download a file from a Spring MVC controler.
#RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
public void getFile(#PathVariable("file_name") String fileName, HttpServletResponse response) {
try {
// get your file as InputStream
InputStream is = ...;
// copy it to response's OutputStream
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
} catch (IOException ex) {
log.info("Error writing file to output stream. Filename was '{}'", fileName, ex);
throw new RuntimeException("IOError writing file to output stream");
}
}
I am using ZipOutputStream,FileOutputStream and FileInputStream.
First I created a folder with one file. It successfully created. Then I tried to create zip files. Dynamically, it creates file first time correctly but at second time , third time it gives error while opening it.
Error: zip [path/././file.zip] Cannot open The process cannot access the file because it is being used by another process.
I created following code in java,
My Code:
demopath+="/myzip"+po.getPoid();
createDir(demopath);
createFileForFamilies("My content", demopath+"/file");
this.zipDirectory(new File(demopath), demopath+".zip");
My file creator function:
public String createFileForFamilies(String content, String path) {
FileOutputStream fop = null;
File file;
try {
file = new File(path);
fop = new FileOutputStream(file);
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
// get the content in bytes
byte[] contentInBytes = content.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();
return ("Done");
} catch (IOException e) {
System.err.println(e);
return ("Done");
} finally {
try {
if (fop != null) {
fop.close();
}
} catch (IOException e) {
System.err.println(e);
return ("Abort");
}
}
}
My Zip creation function:
public void zipDirectory(File dir, String zipDirName) {
try {
populateFilesList(dir);
//now zip files one by one
//create ZipOutputStream to write to the zip file
FileOutputStream fos = new FileOutputStream(zipDirName);
ZipOutputStream zos = new ZipOutputStream(fos);
for (String filePath : filesListInDir) {
System.out.println("Zipping " + filePath);
//for ZipEntry we need to keep only relative file path, so we used substring on absolute path
ZipEntry ze = new ZipEntry(filePath.substring(dir.getAbsolutePath().length() + 1, filePath.length()));
zos.putNextEntry(ze);
//read the file and write to ZipOutputStream
FileInputStream fis = new FileInputStream(filePath);
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
fis.close();
}
zos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Thank you Boris...
This is a solution:
Map<String, String> env = new HashMap<>();
env.put("create", "true");
// locate file system by using the syntax
// defined in java.net.JarURLConnection
URI uri = URI.create("jar:file:/"+zipPath+".zip");
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
java.nio.file.Path externalTxtFile;
java.nio.file.Path pathInZipfile ;
externalTxtFile = Paths.get(gamesPath);
pathInZipfile = zipfs.getPath("/file.txt");
Files.copy(externalTxtFile, pathInZipfile,
StandardCopyOption.REPLACE_EXISTING);
}
I want to compress the dynamic created content and write to ServletOutputStream directly, without saving it as a file on the server before compressing.
For example, I created an Excel Workbook and a StringBuffer that includes strings with the SQL template. I don't want to save the dynamic content to .xlsx and .sql file on the server before zipping the files and writing to ServletOutputStream for downloading.
Sample Code:
ServletOutputStream out = response.getOutputStream();
workbook.write(byteArrayOutputStream);
zipIt(byteArrayOutputStream,out);
public static boolean zipIt(ByteArrayOutputStream input, ServletOutputStream output) {
try {
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(output));
ZipEntry zipEntry = new ZipEntry("test.xlsx");
zos.putNextEntry(zipEntry);
if (input != null) {
zipEntry.setSize(input.size());
zos.write(input.toByteArray());
zos.closeEntry();
}
} catch (IOException e) {
logger.error("error {}", e);
return false;
}
return true;
}
Create an HttpServlet and in the doGet() or doPost() method create a ZipOutputStream initialized with the ServletOutputStream and write directly to it:
resp.setContentType("application/zip");
// Indicate that a file is being sent back:
resp.setHeader("Content-Disposition", "attachment;filename=test.zip");
// workbook.write() closes the stream, so we first have to
// write it to a "buffer", a ByteArrayOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
byte[] data = baos.toByteArray();
try (ZipOutputStream out = new ZipOutputStream(resp.getOutputStream())) {
// Here you can add your content to the zip
ZipEntry e = new ZipEntry("test.xlsx");
// Configure the zip entry, the properties of the file
e.setSize(data.length);
e.setTime(System.currentTimeMillis());
// etc.
out.putNextEntry(e);
// And the content of the XLSX:
out.write(data);
out.closeEntry();
// You may add other files here if you want to
out.finish();
} catch (Exception e) {
// Handle the exception
}
}
I have the below code got from mkyong, to zip files on local. But, my requirement is to zip files on server and need to download that. Could any one help.
code wrote to zipFiles:
public void zipFiles(File contentFile, File navFile)
{
byte[] buffer = new byte[1024];
try{
// i dont have idea on what to give here in fileoutputstream
FileOutputStream fos = new FileOutputStream("C:\\MyFile.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze= new ZipEntry(contentFile.toString());
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream(contentFile.toString());
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
in.close();
zos.closeEntry();
//remember close it
zos.close();
System.out.println("Done");
}catch(IOException ex){
ex.printStackTrace();
}
}
what could i provide in fileoutputstream here? contentfile and navigationfile are files i created from code.
If your server is a servlet container, just write an HttpServlet which does the zipping and serving the file.
You can pass the output stream of the servlet response to the constructor of ZipOutputStream and the zip file will be sent as the servlet response:
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
Don't forget to set the response mime type before zipping, e.g.:
response.setContentType("application/zip");
The whole picture:
public class DownloadServlet extends HttpServlet {
#Override
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException {
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=data.zip");
// You might also wanna disable caching the response
// here by setting other headers...
try ( ZipOutputStream zos = new ZipOutputStream(response.getOutputStream()) ) {
// Add zip entries you want to include in the zip file
}
}
}
Try this:
#RequestMapping(value="download", method=RequestMethod.GET)
public void getDownload(HttpServletResponse response) {
// Get your file stream from wherever.
InputStream myStream = someClass.returnFile();
// Set the content type and attachment header.
response.addHeader("Content-disposition", "attachment;filename=myfilename.txt");
response.setContentType("txt/plain");
// Copy the stream to the response's output stream.
IOUtils.copy(myStream, response.getOutputStream());
response.flushBuffer();
}
Reference