I am trying to create a file and send as a response so that file can be downloaded. I am not sure how to do it. My current code
String fileName = "fileToBeSaved.csv";
File file = new File(fileName);
FileWriter writer = new FileWriter(file);
writer.append(data);
writer.flush();
writer.close();
Response.ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition","attachment; filename=\"fileName.csv\"");
return response.build();
This code creates a temporary file on my system. And when the browser receives the response it gets the path to file, like "C:/folderName/FileName"...Upon mentioning this path on the browser, I get the option to download the file.
What I want to achieve is:
I want to create a file (But don't want any temporary file to be created on my system) and send as a response. The browser should receive a prompt asking whether to download the file or not as a response.
Can some one guide me what am I doing wrong?
I finally found the way.
Response.ResponseBuilder response = Response.ok();
response.header("Content-Disposition", "attachment; filename=\"filename.csv\"");
response.entity(contentAsString);
return response.build();
If you cannot build a string out of the contents of the file, then a work-around is:
ByteArrayOutputStream bo = new ByteArrayOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(bo));
//for loop can be any content.. I am just showing a represenatation.
for (int i = 0; i < content.size(); i++) {
writer.write(content.get(i));
}
writer.flush();
Response.ResponseBuilder response = Response.ok();
response.type(MediaType.APPLICATION_OCTET_STREAM);
response.header("Content-Disposition", "attachment");
response.entity(bo.toByteArray());
return response.build();
In the above code, I am building a file and sending to GUI. No temporary file was created.
Hope it helps.
Thanks!
Related
I am trying to download csv file from the filepath that is saved in db. I have to read the csv file from filepath and download it when hitting the endpoint. Error I am getting says no converter for class BufferedReader with preset Content-Type 'application-csv'. I think the type I have with response entity BufferedReader is not taking my content-type as csv. I have seen resource type with response entity working fine. And I don't want csv to be generated, I already have it, i just have to read it and download it.
#GetMapping("/export")
public CompletableFuture <ResponseEntity<BufferedReader>> getCSVFile(#RequestParam Integer reportdt,
#RequestParam("conId") String conId) throws IOException {
CSVFilePath csvFilePath = csvFilePathRepository.findByConIdAndReportdt(conId, reportdt);
File file = new File(csvFilePath.getFilepath());
//FileInputStream csvfile = new FileInputStream(csvFilePath.getFilepath());
FileReader newfile = new FileReader(csvFilePath.getFilepath());
String fileName = file.getName();
if(file.exists()) {
return CompletableFuture
.completedFuture(ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName)
.contentType(MediaType.parseMediaType("application/csv"))
.body(new BufferedReader(newfile)));
} else {
return CompletableFuture
.completedFuture(ResponseEntity.status(HttpStatus.NOT_FOUND).body(new BufferedReader(newfile)));
}
}
Here is the error log.
error log
In my program I have a getRequest (JavaSpark) that offers me an Excel file created in Java for download.
To do this, I create the Excel file, save it in a folder and then read the file via the path.
Works.
Code - ExcelCreation:
public void createPlanWorkbook() throws Exception {
...
...
do something with workbook...
workBook.write("C:\\Users\\Develope\\Desktop\\Excel.xlsm");
}
Code - request:
get("/excelfile", ((request, response) -> {
response.header("Content-disposition", "attachment; filename=Excel.xlsm;");
File file = new File("C:\\Users\\Develope\\Desktop\\Excel.xlsm");
OutputStream outputStream = response.raw().getOutputStream();
outputStream.write(Files.readAllBytes(file.toPath()));
outputStream.flush();
return response;
}));
I wonder if there is another way to implement this. Is the step of saving and then reading the file necessary? Or is there a way to put the file directly from Javaobject into the request.
For example:
outputStream.write(ExcelCreaterObject().getWorkbook());
It seems that you are using Apache POI SmartXls to create an Excel workbook. Looking at its Javadoc, it seems that the Workbook.write method accepts an outputstream to write to.
So, you should be able to do write to the response stream directly, something like:
get("/excelfile", ((request, response) -> {
response.header("Content-disposition", "attachment; filename=Excel.xlsm;");
File file = new File("C:\\Users\\Develope\\Desktop\\Excel.xlsm");
OutputStream outputStream = response.raw().getOutputStream();
// do some stuff with the workbook
workbook.write(outputStream);
return response;
}));
Using OpenCSV, I can successfully create a CSV file on disc, but what I really need is to allow users download the CSV with a download button, I don't need to save on disk, just download. Any ideas?
#GET
#Path("/downloadCsv")
public Object downloadCsv() {
CSVWriter writer;
FileWriter wr;
//Or should I use outputstream here?
wr= new FileWriter("MyFile.csv");
writer = new CSVWriter(wr,',');
for (Asset elem: assets) {
writer.writeNext(elem.toStringArray());
}
writer.close();
}
EDIT: I do NOT want to save/read file on disc EVER
To force "save as", you need to set the content disposition HTTP header in the response. It should look like this:
Content-Disposition: attachment; filename="whatever.csv"
It looks like you're using JAX-RS. This question shows how to set the header. You can either write the CSV to the HTTP response stream and set the header there or return a Response object like so:
return Response.ok(myCsvText).header("Content-Disposition", "attachment; filename=" + fileName).build();
You do not need to write to a File object in the middle of this process so can avoid writing to disk.
First, you code cannot be compiled, right? Method downloadCsv() declares return type Object but does not return anything.
I'd change the declaration to String downloadCsv() and return the content of CSV as string. To do this use StringWriter instead of FileWriter and then say return wr.toString().
The only thing that is missing here is content type. You annotate your method as #Produces({"text/csv"}).
I think, that's it.
response.setHeader("Content-Disposition", "attachment; filename=" + filename + ".csv");
response.setContentType("text/csv");
OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
List<String[]> result = iSmsExportService.csvExport(columnNames);
CSVWriter csvWriter = new CSVWriter(osw, ';');
csvWriter.writeAll(result);
csvWriter.flush();
csvWriter.close();
Downloading of CSV file has started after this.
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.
In this situation, I have created a zip file containing search result files, and am trying to send it to the user. Here is the chunk of code I am currently trying to use.
File[] zippable = new File[files.size()];
File resultFile = ZipCreator.zip(files.toArray(zippable), results);
InputStream result = new FileInputStream(resultFile);
IOUtils.copy(result, response.getOutputStream());
However, this currently doesn't work quite right. Instead of returning the zip file that I have created, it returns an html file. If I manually change the file extension afterwards, I can see that the contents of the file are still the search results that I need. So the problem just lies in returning the proper extension to the response.
Does anyone have any advice for this situation?
You need to set the Content-Type response header to the value application/zip (or application/octet-stream, depending on the target browser). Additionally, you may want to send additional response headers indicating attachment status and filename.
You need to set the content type header to application/octet-stream prior to streaming the results. Depends on what implementation of response you are using on how you actually do this.
Here is some working code, just in case anyone needs it:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// The zip file you want to download
File zipFile = new File(zipsResourcesPath + zipFileName);
response.setContentType("application/zip");
response.addHeader("Content-Disposition", "attachment; filename=" + zipFileName);
response.setContentLength((int) zipFile.length());
try {
FileInputStream fileInputStream = new FileInputStream(zipFile);
OutputStream responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
} catch (IOException e) {
logger.error("Exception: " + e);
}
}
And the HTML:
<a class="btn" href="/path_to_servlet" target="_blank">Download zip</a>
Hope this helps!
So I found a hack for this : ) Just add ".zip" in your filename and set your content type as application/zip. Works like a charm.
response.setContentType("application/zip");
String licenseFileName = eId;
response.setHeader("Content-disposition", "attachment; filename=\"" + licenseFileName +".zip");