I have an ADF Table in JSF page that is bounded to View Object which holds user's uploaded files. This View Object contains all the information needed to download a file like blob domain , file type and file name. For each row there is a download button that enables the user to download the selected file.
Every things works perfectly for the first time. Problem is when the user press the download button for some file he/she already download it, the file get corrupted. The file appears in the download section for browser, but when I tried to open it tells that the file can not be open because the file format or file extension is not supported.
here is the button in the JSF page:
<af:column id="c31">
<af:commandButton text="Download" id="cb12" partialSubmit="true">
<af:fileDownloadActionListener method="#{ITDetalisBean.downloadSelectedFile}"
filename="#{row.FileName}" contentType="#{row.FileType}"/>
</af:commandButton>
</af:column>
As you can see the button is placed in <af:column> tag. So for each file row there is corresponding download button.
Here is the Bean method:
public void downloadSelectedFile(FacesContext facesContext, OutputStream outputStream)
{
// get the view object from the application module
AppModuleImpl appM = (AppModuleImpl)(JSFUtils.getApplicationModule("AppModuleDataControl"));
ViewObject fileUploadedVO = appM.findViewObject("UplodedFilesViewTransient1");
// get the file content as blob domain from the current row
BlobDomain blobDomain=(BlobDomain)fileUploadedVO.getCurrentRow().getAttribute("FileContn");
// download the file using output stream
try {
HttpServletResponse response =
(HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
InputStream in = blobDomain.getBinaryStream();
outputStream = response.getOutputStream();
byte[] buf = new byte[1024];
int count;
while ((count = in.read(buf)) >= 0) {
outputStream.write(buf, 0, count);
}
in.close();
outputStream.flush();
outputStream.close();
facesContext.responseComplete();
} catch (IOException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
Problem solved by adding the following:
blobDomain.closeInputStream();
blobDomain.closeOutputStream();
at the end of try block before the last statement facesContext.responseComplete();
Minor Change:
I was getting the outputstream by this line: outputStream = response.getOutputStream();
Instead I should use the outputstream that's come with method as an argument:
public void downloadSelectedFile(FacesContext facesContext, OutputStream outputStream)
Related
This question already has answers here:
How do I create a file and write to it?
(35 answers)
Closed 1 year ago.
I'm working on a new function on a system, and at the moment I need to pick a file, and save on a folder in the user C:. The process happens as it follows, the user uploads a file into the system, that file can be anything, text, image, except videos, and now it is saved in the system database, but my boss wants to change that process so I need to save on a specific folder on the user C:, I already created the specific folder, but I don't know how to save the file in that created folder.
So the code for uploading a file as it follows:
public void uploadArquivo(FileUploadEvent event) {
byte[] bytes = null;
try {
File targetFolder = new File(System.getProperty("java.io.tmpdir"));
if (!targetFolder.exists()) {
if (targetFolder.mkdirs()) {
FacesMessageUtil.novaMensagem("Atenção", "Não foi possível criar pasta temporária!");
return;
}
}
targetFolder.mkdirs();
OutputStream out;
try (InputStream inputStream = event.getFile().getInputstream()) {
out = new FileOutputStream(new File(targetFolder, event.getFile().getFileName()));
int read;
bytes = new byte[10485760];
while ((read = inputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
inputStream.close();
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace(System.out);
}
AnexoEmpreendimento anexo = new AnexoEmpreendimento();
anexo.setNomeArquivo(event.getFile().getFileName());
anexo.setTamanhoArquivo(event.getFile().getSize());
anexo.setArquivo(bytes);
anexos.add(anexo);
}
Well, it depends on what you actually 'have'. A web submit form? Which web framework do you have then? A BLOB in a db? Which DB engine do you have and which DB framework are you using in java to interact with it, etcetera.
Most libraries will let you obtain either an InputStream or a byte[] (if they offer both, you want the InputStream).
You can write an inputstream to a file, or a byte[] to a file, as follows:
import java.nio.file.*;
public class Example {
static final Path MY_DIR = Paths.get("C:/path/to/your/dir");
void writeByteArr(byte[] data) throws IOException {
Path toWrite = MY_DIR.resolve("filename.dat");
Files.write(toWrite, data);
}
void writeInputStream(InputStream data) throws IOException {
Path toWrite = MY_DIR.resolve("filename.dat");
Files.copy(data, toWrite);
}
}
In the unlikely case the data you 'get' is neither in byte[] nor InputStream form you're going to have to elaborate quite a bit on how the data gets to your code.
I followed the discussion on spark github page as well as stack overflow to understand how to upload files using spark and apache file uploads.
Now I want the user to have an option to download the image on click.
For example my uploaded files get stored in /tmp/imageName.jpg on the server.
On the client side i want to give the user an option to download the file when the user clicks in the hyperlink.
click here
When the user click on the hyperlink I will call the function with the file path but can't understand how to send the image in response.
I do know that HTML5 has download attribute but that would require the files to be kept in public folder on the server which is not possible.
I went through the previous similar question add tried to replicate for my scenario without success
How can I send a PNG of a QR-code in a HTTP response body (with Spark)?
How download file using java spark?
Edit:
I did follow the link provided in the answer to force download the image, but using response.raw() i'm not able to get the response
response.type("application/force-download");
response.header("Content-Transfer-Encoding", "binary");
response.header("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName);
try {
HttpServletResponse raw = response.raw();
PrintWriter out = raw.getWriter();
File f= new File("/tmp/Tulips.jpg");
InputStream in = new FileInputStream(f);
BufferedInputStream bin = new BufferedInputStream(in);
DataInputStream din = new DataInputStream(bin);
while(din.available() > 0){
out.print(din.read());
out.print("\n");
}
}
catch (Exception e1) {
e1.printStackTrace();
}
response.status(200);
return response.raw();
Edit 2:
I'm not sure what is the difference between using response.body () vs response.raw().someFunction(). In either case I can seem to send the data back in response. Even if i write a simple response.body("hello") it doesn't reflect in my response.
Is there a difference in how a file would be read as opposed to an image ? Exampling using ImageIO class ?
Below is the solution that work for me:
Service.java
get(API_CONTEXT + "/result/download", (request, response) -> {
String key = request.queryParams("filepath");
Path path = Paths.get("/tmp/"+key);
byte[] data = null;
try {
data = Files.readAllBytes(path);
} catch (Exception e1) {
e1.printStackTrace();
}
HttpServletResponse raw = response.raw();
response.header("Content-Disposition", "attachment; filename=image.jpg");
response.type("application/force-download");
try {
raw.getOutputStream().write(data);
raw.getOutputStream().flush();
raw.getOutputStream().close();
} catch (Exception e) {
e.printStackTrace();
}
return raw;
});
Angular Code
$scope.downloadImage= function(filepath) {
console.log(filepath);
window.open('/api/v1/result/download?filepath='+filepath,'_self','');
}
I am creating desktop JavaFX application for viewing PDF files. PDFs are at resource folder. I read resourse file as stream, then I create temporary file and use it to convert contents to image and show into ImageView.
currentPdf = new File("current.pdf");
if (!currentPdf.exists()) {
// In JAR
InputStream inputStream = ClassLoader.getSystemClassLoader()
.getResourceAsStream("PDFSample.pdf");
// Copy file
OutputStream outputStream;
try {
outputStream = new FileOutputStream(currentPdf);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
byte[] buffer = new byte[1024];
int length;
try {
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.close();
inputStream.close();
} catch(IOException e) {
throw new RuntimeException(e);
}
}
The problem is: when I create regular file with
currentPdf = new File("current.pdf");
Everything works as expected (i get current.pdf created at directory where jar is located). But I want the file to be created at system temp folder and to be deleted on exit from application. I tried this:
try {
currentPdf = File.createTempFile("current",".pdf");
} catch (IOException e) {
throw new RuntimeException(e);
}
currentPdf.deleteOnExit();//also tried to comment this line
And get exception:
Caused by: java.io.IOException: Error: End-of-File, expected line
at org.apache.pdfbox.pdfparser.BaseParser.readLine(BaseParser.java:1517)
at org.apache.pdfbox.pdfparser.PDFParser.parseHeader(PDFParser.java:360)
at org.apache.pdfbox.pdfparser.PDFParser.parse(PDFParser.java:186)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1227)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1194)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1165)
at ua.com.ethereal.pdfquiz.Controller.getPdfPageAsImage(Controller.java:147)
At this method:
#SuppressWarnings("unchecked")
public static Image getPdfPageAsImage(File pdfFile, int pageNum) {
Image convertedImage;
try {
PDDocument document = PDDocument.load(pdfFile);
List<PDPage> list = document.getDocumentCatalog().getAllPages();
PDPage page = list.get(pageNum);
BufferedImage image = page.convertToImage(BufferedImage.TYPE_INT_RGB, 128);
convertedImage = SwingFXUtils.toFXImage(image, null);
document.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
return convertedImage;
}
Would appreciate help in resolving this or pointing me on way to read file directly from jar to avoid creating temporary copies.
How do you create the temporary file?
The usual methods make an empty file in the filesystem. That will trip your logic here:
if (!currentPdf.exists()) {
That check is supposedly there to avoid overwriting exiting files, but in this case you have to get rid of it. As it is, you skip your PDF generation code and try to read an empty file.
I am working on Java ExtJS application in which I need to create and download a CSV file.
On clicking a button I want a CSV file to be downloaded to a client's
machine.
On buttons listener I am calling a servlet using AJAX. There I am
creating a CSV file.
I don't want the CSV file to be saved in the server. I want the file should be created dynamically with a download option. I want the contents of a file to be created as a string and then I will serve the content as file in which it will open as download mode in browser (this I have achieved in other language, but not sure how to achieve it in Java).
Here is my code only to create a CSV file, but I really don't want to create or save CSV file if I can only download the file as CSV.
public String createCSV() {
try {
String filename = "c:\\test.csv";
FileWriter fw = new FileWriter(filename);
fw.append("XXXX");
fw.append(',');
fw.append("YYYY");
fw.append(',');
fw.append("ZZZZ");
fw.append(',');
fw.append("AAAA");
fw.append(',');
fw.append("BBBB");
fw.append('\n');
CSVResult.close();
return "Csv file Successfully created";
} catch(Exception e) {
return e.toString();
}
}
Can any one help me on this.
Thanks
I got the solution and I am posting it below.
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
response.setContentType("text/csv");
response.setHeader("Content-Disposition", "attachment; filename=\"userDirectory.csv\"");
try
{
OutputStream outputStream = response.getOutputStream();
String outputResult = "xxxx, yyyy, zzzz, aaaa, bbbb, ccccc, dddd, eeee, ffff, gggg\n";
outputStream.write(outputResult.getBytes());
outputStream.flush();
outputStream.close();
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
Here we don't need to save / store the file in the server.
Thanks
First of all you need to get the HttpServletResponse object so that you can stream a file into it.
Note : This example is something I Wrote for one of my projects and it works.Works on Java 7.
Assuming you got the HttpServletResponse you can do something like this to stream a file. This way the file will be saved into clients' machine.
public void downloadFile(HttpServletResponse response){
String sourceFile = "c:\\source.csv";
try {
FileInputStream inputStream = new FileInputStream(sourceFile);
String disposition = "attachment; fileName=outputfile.csv";
response.setContentType("text/csv");
response.setHeader("Content-Disposition", disposition);
response.setHeader("content-Length", String.valueOf(stream(inputStream, response.getOutputStream())));
} catch (IOException e) {
logger.error("Error occurred while downloading file {}",e);
}
}
And the stream method should be like this.
private long stream(InputStream input, OutputStream output) throws IOException {
try (ReadableByteChannel inputChannel = Channels.newChannel(input); WritableByteChannel outputChannel = Channels.newChannel(output)) {
ByteBuffer buffer = ByteBuffer.allocate(10240);
long size = 0;
while (inputChannel.read(buffer) != -1) {
buffer.flip();
size += outputChannel.write(buffer);
buffer.clear();
}
return size;
}
}
What this does is, get an inputstream from your source file and write that stream into the outputstream of the HttpServletResponse. This should work since it works perfectly for me. Hope this helps. Sorry for my bad English.
I would like add something to the answer by gaurav. I recently had to implment this functionality in a project of mine and using javascript was out of the question becuase we had to support IE 9. What is the problem with IE 9?
(Export to CSV using jQuery and html), see the second answer in the link.
I needed an easy way to convert a ResultSet of a database query to a string which represent the the same data in CSV format. For that I used http://opencsv.sourceforge.net/ which provided an easy way to get a String ot of the ResultSet, and the rest is as above answer did it.
THe examples in the project soruce folder give good examples.
I am trying to show pdf document in a iframe. I have set the source of the iframe to a servlet and passing some parameter to the servlet.
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String docName = request.getParameter("docName");
String id = request.getParameter("id");
if (StringUtils.isNotBlank(id) && StringUtils.isNotBlank(docName)) {
DocumentService service = DamServiceProvider.PROVIDER.getDocumentService();
FileInBean fileInBean = new FileInBean();
fileInBean.setDocName(docName);
fileInBean.setId(Integer.valueOf(id));
FileDataBean fileDataBean = service.getFileDataBean(fileInBean);
if (fileDataBean.getStatusCode() == 0) {
Map<String, String> headerFieldMap = fileDataBean.getHeaderFieldMap();
String contentType = headerFieldMap.get("Content-type");
String contentLength = headerFieldMap.get("Content-Length");
String contentDisposition = headerFieldMap.get("Content-Disposition");
byte[] stream = fileDataBean.getStream();
ByteArrayInputStream inputStream = new ByteArrayInputStream(stream);
OutputStream outputStream = response.getOutputStream();
response.reset();
response.setBufferSize(4096);
response.setContentLength(Integer.valueOf(contentLength));
response.setContentType(contentType);
response.setHeader("Content-Disposition", contentDisposition);
System.out.println(contentDisposition);
IOUtils.copy(inputStream, outputStream);
outputStream.close();
inputStream.close();
}
}
} catch (Exception ex) {
Log.error(this, ex.getMessage());
}
}
Now in my page I have a master–detail interface. The master part contains a carousel of series of pdf file items. On clicking the item I am refreshing the detail view which contains the iframe.
I can see the servlet get called. Most of the times the iframe is displaying the pdf document. But sometimes it is showing weird xml structure which contains xml tags and some unreadable output. Please see the attach image:
This is not happening for a particular file. If a file shows this output, sometime later if click the item it shows the valid pdf and if an item shows a valid pdf sometime later it shows this kind of output if I click on it. When the iframe shows this type of output my browser displays an information that this pdf document might be corrupted.
I have checked the repository where the files are and I have found no issues there. All of them are valid pdf and I can download and open them by pdf reader.
I am unable to find the cause of this issue. Any pointer would be very helpful.
Update - 1
I have checked the output. It ends with %%EOF and has %PDF in the beginning.
Update - 2
I have checked in Chrome's Network Console the GET is returning mainly three types of content-type: application/pdf, text/plain, application/octet-stream.
application/pdf: it is showing the pdf.
text/plain it is showing the content that I mentioned above.
application/octet-stream didn't arise in Firefox but in Chrome and in that case it is opening the download file window.
I have placed a log in the servlet to see the content-type that returned from service. For all the cases it is application/pdf.
I think it maybe a problem with the content-Type, you can confirm if this is the espected in your browser with the developer tools (in the network console for Chrome).
try something like this.
File pdfFile = new File(this.pdfStoreLocation + pdfFileName);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + pdfFileName);
response.setContentLength((int) pdfFile.length());
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pdfFile));
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
// byte array declared
byte[] buf = new byte[2048];
boolean eof = false;
while (!eof) {
int length = bis.read(buf);
if (length == -1) {
eof = true;
}else {
bos.write(buf, 0, length);
}
}
try {
bis.close();
}catch (IOException ex) {
LOGGER.error("Exception in closing buffered input stream on pdf file->" + this.pdfStoreLocation + pdfFileName);
}
try {
bos.flush();
}catch (IOException ex) {
LOGGER.error("Exception in fliushing buffered output stream on pdf file->"
+ this.pdfStoreLocation + pdfFileName);
}
bos.close();