Why is my .xslm file corrupted during download? - java

So here is the situation:
I have a .xslm file (a macro enabled excel worksheet) on server. There are no issues in opening this file on server (using ms-excel 2013).
I then edit the file using Apache POI 3.13. Save a copy of this file on server and give the other to the user for download.
(This is done just to check if we have any write issues while editing. The original purpose was just to give it as download)
The copy of this file saved on server is opened without any issues. But the one sent as download throws this error while opening it from excel 2013.
I am using Jquery.fileDownload() on the client side to make the ajax call to the server where I have my Spring Controller serving the file.
Here is my code to write the file:
Workbook workbook = null;
ServletOutputStream out = null;
InputStream inputStream = null;
FileOutputStream fos = null;
try {
OPCPackage inputFilePackage = OPCPackage.open(<original file saved on server>);
workbook = WorkbookFactory.create(inputFilePackage);
//Do Some stuff to edit workbook here
fos = new FileOutputStream("temp.xlsm");
workbook.write(fos);
fos.close();
inputStream = new FileInputStream("temp.xlsm"); // The file that is created just now
servletResponse.setContentType("application/vnd.ms-excel.sheet.macroEnabled.12");
servletResponse.setHeader("content-disposition", "attachment; filename=NewFile.xlsm");
servletResponse.setHeader("Set-Cookie", "fileDownload=true; path=/");
out = servletResponse.getOutputStream();
// workbook.write(out); // Was previously using this method to directly write to ServletOutputStream
int i;
while ((i = inputStream.read()) != -1) {
out.write(i);
}
out.flush();
// new File("temp.xlsm").delete();
}
catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
finally {
if (out != null) {
try {
out.close();
}
catch (Exception ex) {
LOGGER.error(ex.getMessage());
}
}
if (inputStream != null) {
try {
inputStream.close();
}
catch (Exception ex) {
LOGGER.error(ex.getMessage());
}
}
}
return "success";
Also I can clearly see the difference between the size of both the files.
The file which is opening without issues is (436,129 bytes) while the file throwing the error is (436,136 bytes). I am not sure from where these extra bytes are coming.
Any help would be greatly appreciated.

Related

How to encrypt an excel in an InputStream and write to an OutputStream?

I'm using this within an application where writing to a file is not possible. The data is always in streams. I get the XLSX file in an inputstream and I would like to set a password and write it to an outputstream.
public void encrptXslxFile(InputStream inStream, OutputStream outStream){
POIFSFileSystem fs = null;
EncryptionInfo info = null;
OutputStream fos;
OPCPackage opc = null;
try {
info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("coffee");
//inStream = new FileInputStream("C:\\ProjectWork\\Community\\excelfile.xlsx");
fs = new POIFSFileSystem();
opc = OPCPackage.open(inStream); //from parameter
OutputStream os = enc.getDataStream(fs);
opc.save(os);
os.close();
//fos = new FileOutputStream("C:\\ProjectWork\\Community\\excelfilepwd.xlsx");
//fs.writeFilesystem(fos);
//fos.close();
fs.writeFilesystem(outStream); // from parameter
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
While reading from the file and writing to the file, it encrypts fine. But if I use the function and then get the outputstream, and later write it, it creates a zero kb file.
Is this even possible?
I tested with the code below to makes sure the inputstream is good.
public void encrptXslxFile(InputStream inStream, OutputStream outStream){
try {
IOUtils.copy(inStream, outStream);
} catch (IOException e) {
e.printStackTrace();
}
}
I was able to write the outputstream to a file.
Since I cannot create files and POI internally uses files, I had to specifically set the temp directory for POI to use.
TempFile.setTempFileCreationStrategy(new TempFileCreationStrategy() {
#Override
public File createTempFile(String prefix, String suffix) throws IOException {
// check dir exists, make if doesn't
if(!fileTempDir.exists()){
fileTempDir.mkdir();
fileTempDir.deleteOnExit();
}
File newFile = File.createTempFile(prefix, suffix, fileTempDir);
return newFile;
}
#Override
public File createTempDirectory(String strPath) throws IOException {
if(!fileTempDir.exists()){
fileTempDir.mkdir();
fileTempDir.deleteOnExit();
return fileTempDir;
}else {
return Files.createTempDirectory(strPath).toFile();
}
}
});
This worked for me.

how to make the file uploading to ftp faster

we are using below code to upload files back to the FTP server?
basically 60 MB file is taking 3 minutes to upload to ftp server.Is there any way to make it faster?Please note that uploadable file(input file) and ftp server, both are on the same host but still its taking this much time.
at this line client.storeFile(filename, fis) its taking maximum time.
FTPClient client = new FTPClient();
FileInputStream fis = null;
try {
client.connect("ftp.domain.com");
client.login("admin", "secret");
//
// Create an InputStream of the file to be uploaded
//
String filename = "sample.zip";
fis = new FileInputStream(filename);
//
// Store file to server
//
client.storeFile(filename, fis);
client.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}

Java HttpServlet how to download excel file

I am trying to add a function to my web app which lets the users download an excel file.
I'm trying to achieve this with the following code:
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
File file = new File("d:/test/test.xls");
response.setContentType("application/xls");
response.addHeader("Content-Disposition", "attachment; filename=test.xls");
response.setContentLength((int) file.length());
try {
FileInputStream fileInputStream = new FileInputStream(file);
OutputStream responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
fileInputStream.close();
responseOutputStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I'm able to download the excel file with the above code, however the file is corrupted. If I open it with microsoft excel, I get a popup with the message:
"the file format and extension of don't match. the file could be corrupted or unsafe".
And the excel file is empty.
After running the code, the original file(d:/test/test.xls) gets also corrupted.
What am I doing wrong?
The official MIME type for Excel file .xls is application/vnd.ms-excel and for .xlsx is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.
Also, I would suggest doing response.reset() prior to writing to the output stream and responseOutputStream.flush() (important) prior to closing the response.
Try below code :
File file = null;
InputStream in = null;
OutputStream outstream = null;
try {
response.reset();
in = new FileInputStream(file);
response.setContentType("application/vnd.ms-excel");
response.addHeader("content-disposition", "attachment; filename=data.xls");
outstream = response.getOutputStream();
IOUtils.copyLarge(in, outstream);
}
catch (Exception e) {
out.write("Unable to download file");
}finally {
IOUtils.closeQuietly(outstream);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
if (file != null)
file.delete();
}
dont forgot to add apache commons-io-2.4 in your dependency

Missing bytes when calling HttpServletRequest.getInputSteam() method

I am creating Restful web service that accepts any file and saves it into filesystem. I am using Dropwizard to implement the service and Postman/RestClient to hit the request with data. I am not creating multipart (form-data) request.
Every thing is working fine except the file saved has first character missing. Here is my code for calling the service method and saving it into file system:
Input Request:
http://localhost:8080/test/request/Sample.txt
Sample.txt
Test Content
Rest Controller
#PUT
#Consumes(value = MediaType.WILDCARD)
#Path("/test/request/{fileName}")
public Response authenticateDevice(#PathParam("fileName") String fileName, #Context HttpServletRequest request) throws IOException {
.......
InputStream inputStream = request.getInputStream();
writeFile(inputStream, fileName);
......
}
private void writeFile(InputStream inputStream, String fileName) {
OutputStream os = null;
try {
File file = new File(this.directory);
file.mkdirs();
if (file.exists()) {
os = new FileOutputStream(this.directory + fileName);
logger.info("File Written Successfully.");
} else {
logger.info("Problem Creating directory. File can not be saved!");
}
byte[] buffer = new byte[inputStream.available()];
int n;
while ((n = inputStream.read(buffer)) != -1) {
os.write(buffer, 0, n);
}
} catch (Exception e) {
logger.error("Error in writing to File::" + e);
} finally {
try {
os.close();
inputStream.close();
} catch (IOException e) {
logger.error("Error in closing input/output stream::" + e);
}
}
}
In output, file is saved but first character from the content is missing.
Output:
Sample.txt:
est Content
In above output file, character T is missing and this happens for all the file formats.
I don't know what point I am missing here.
Please help me out on this.
Thank You.

Can't delete file after it gets written

I'll put my code first:
#Post
public Representation post(InputStream zip) throws Throwable {
createFile(zip, "C:/temp");
return new StringRepresentation("File uploaded");
}
public void createFilee(InputStream zipStream, uploadedFileLocation) throws Exception {
try {
writeToFile(zipStream, uploadedFileLocation);
FileUtils.forceDelete(new File(uploadedFileLocation));
} catch (Exception e) {
throw e;
}
}
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();
uploadedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
When I send a file to my server, it cannot get deleted. When using FileUtils.forceDelete(), it says that it cannot delete the file. I can delete the file manually while the server is still running after it tries to delete the file with file utils. Why can't it just delete it itself?! any ideas? Thanks
EDIT: Could the issue be that the InputStream from the POST is alive until the POST returns? So, even when I call to delete the file, the stream is still kept alive by the POST? Is this even possible?
In my limited windows experience it can be one of the two things
I would check
1) THe anti-virus software is trying to scan the file
2) Some kind of indexer (System or custom) is trying to index the file.
you can use a tool like processExplorer to see which process holding up the file descriptor.
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

Categories

Resources