.zip file downloaded as f.txt file - springboot - java

Below code is always downloading a f.txt file rather downloading without the actual file name and extension(here .zip extension).
#RequestMapping(value = "/files/{fileId}", method = RequestMethod.GET, produces = "application/zip")
public ResponseEntity<Resource> downloadFile(#PathVariable("fileId") String fileName) {
log.info("Downloading file..!!!!");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/zip"));
log.info("Content info : "+headers.getContentType().toString());
File file = FileUtils.getFile("backup/" + fileName + ".zip");
log.info("File name is : "+file.getName());
FileSystemResource fileSystemResource = new FileSystemResource(file);
return new ResponseEntity<>(fileSystemResource, headers, HttpStatus.OK);
}
It would be great if someone can let me know where the mistake is/ some amendments to be done?

f.txt is coming from the Content-Disposition response header. This is a consequence of fixing cve-2015-5211 (RFD Attack)

To fix the issue, add the content-disposition and content-length headers:
...
log.info("File name is : "+file.getName());
// Adding the following two lines should fix the download for you:
headers.set("content-disposition", "inline; filename=\"" + file.getName() + "\"");
headers.set("content-length", String.valueOf(file.length()));
FileSystemResource fileSystemResource = new FileSystemResource(file);
...

Related

download csv from filepath in java

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

Posting FileList in RestAssured

Currently I use the below code to post single file using RestAssured.
RestAssured.given().contentType(ContentType.MULTIPART_FORM_DATA.toString()).request().multiPart("files", ScreenshotFile).post().then().statusCode(200);
However I want to upload multiple files from the below mentioned FileList.
File ScreenShotFolder = new File("C:\\Users\\1451615\\Desktop\\SessionScreenshot\\");
File ScreenShotFiles[] = ScreenShotFolder.listFiles();
I have put a for loop to post multiple files in the same request. Please find below the code for same.
File ScreenShotFolder = new File("C:\\Users\\1451615\\Desktop\\SessionScreenshot\\");
File ScreenShotFiles[] = ScreenShotFolder.listFiles();
RestAssured.baseURI = "http://10.141.188.112:7080/PIMSelfService/testing/uploadResultImg";
RequestSpecification request = RestAssured.given().contentType(ContentType.MULTIPART_FORM_DATA.toString()).request();
for (File file: ScreenShotFiles) {
System.out.println("File name: " + file.getName());
String FilePath = file.getAbsolutePath();
File ScreenShotPath = new File(FilePath);
System.out.println(ScreenShotPath);
request.multiPart("files", ScreenShotPath);
}
request.post().then().statusCode(200);
ValidatableResponse createAttachemnetResponse = expect()
.given()
.spec(requestSpecification)
.header("content-type", "multipart/form-data")
.multiPart("files-0", new File("testImages/1.jpg"))
.multiPart("files-1", new File("testImages/2.png"))
.multiPart("files-2", new File("testImages/3.png"))
.multiPart("files-3", new File("testImages/4.png"))
.multiPart("files-4", new File("testImages/5.png"))
.formParams("txn_id", transactionId)
.when()
.post(TRANSACTION_BASEPATH + POST_ATTACHMENT)
.then()
.spec(responseSpecification);

File Extension getting changed for few content types when downloaded

I am using the below method to download the file from server now for few files with extensions (".png",".txt",".pdf") the files are downloading correctly but where as for (".exe") the file is downloading as f.txt may i know what's wrong with this code.For .exe files the content is being written to a "f.txt" file . I am also usoing Files.probeContentType(file.toPath()); to determine the media type and setting it in content type of respnse entity.Thanks in advance! :).
the media type where extension changing is application/x-msdownload
public ResponseEntity<InputStreamResource> getFileFromDisk(String filename) throws IOException {
ResponseEntity<InputStreamResource> filedata = null;
String file_path = "/e:/filesfolder/" + filename;
String fileType = "Undetermined";
final File file = new File(file_path);
fileType = Files.probeContentType(file.toPath());
System.out.println(fileType);
InputStreamResource resource = new InputStreamResource(new FileInputStream(file_path));
String file_checksum = checksumcalc.calculateChecksum(file_path);
filedata = ResponseEntity.ok().header("Md5", file_checksum)
.contentType(MediaType.parseMediaType(fileType)).body(resource);
return filedata;
}
To avoid the f.txt issue, you have to define the Content-disposition header to specify the filename of the attachment.
For example :
filedata = ResponseEntity.ok()
.header("Content-disposition", "attachment; filename=" + fileName)
.header("Md5", file_checksum)
.contentType(MediaType.parseMediaType(fileType)).body(resource);

How do I return a zip file to the browser via the response OutputStream?

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");

Firefox will not download this file as a CSV

I have tried everything I can think of. I have changed the mime type 100 times. Changed the headers 400 times. I've looked through stack over flow a dozen times. This works fine in Chrome. Soon as I go to download in Firefox it thinks it's a xlsx file, or a binary file. It even opens as an xlsx but it doesn't think it's a csv so the columns aren't seperated. If I save the file(instead of just hit open) it doesn't even put the extension on. I haven't even got to IE yet so this is kind of worrying me.
mime mapping
<mime-mapping>
<extension>csv</extension>
<mime-type>application/vnd.ms-excel</mime-type>
</mime-mapping>
I've tried text/csv, application/csv, application/binary, application/octet-stream.
public void doDownloadFile() {
PrintWriter out = null;
try {
String fileName = selectedPkgLine.getShortname() + ".csv";
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
response.setHeader("Pragma", "public");
response.setHeader("Expires", "0");
response.setContentType(request.getServletContext().getMimeType(fileName));
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Content-disposition", "attachment; filename=" + fileName + "");
response.setHeader("Content-Transfer-Encoding", "binary");
out = response.getWriter();
CSVWriter writer = new CSVWriter(out);
List<PkgLoad> pkgLoadList = pkgLoadService.findBetweenDates(selectedPkgLine, startDate, endDate);
List<String[]> stringList = new ArrayList<String[]>();
stringList.clear();
String[] header = {
"pkg_load_id",
"time_stamp",
"ounces",
"revolutions",
"wrap_spec_id",
"pkg_line_id"
};
stringList.add(header);
for (PkgLoad pkgLoad : pkgLoadList) {
String[] string = {
pkgLoad.getPkgLoadId().toString(),
pkgLoad.getTimeStamp().toString(),
pkgLoad.getOunces().toString(),
pkgLoad.getRevolutions().toString(),
pkgLoad.getWrapSpecId().getWrapSpecId().toString(),
pkgLoad.getPkgLineId().getPkgLineId().toString()
};
stringList.add(string);
}
response.setHeader("Content-length", String.valueOf(stringList.size()));
writer.writeAll(stringList);
out.flush();
} catch (IOException ex) {
Logger.getLogger(ViewLines.class.getName()).log(Level.SEVERE, null, ex);
} finally {
out.close();
}
}
Thanks for any help.
Safari, Opera and Chrome work fine. Haven't tried IE.
****EDIT****
Ok this entire time it was a spacing issue. My file name was "file name.csv" and this works in every browser except firefox. Soon as I put my file name to "filename.csv with no spaces it downloaded it find. I didn't notice that when it was downloading it was only downloading the first part of the name before the space. Good luck!
I had the same issue in PHP and found adding double quotes for the file name fixes the problem.
response.setHeader("Content-disposition", "attachment; filename=\"" + fileName + \"");
The content type text/csv is correct, but you should also add an charset encoding:
response.setHeader("Content-type: text/csv; charset=utf-8");
But what the hell is this:
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-length", String.valueOf(stringList.size()));
Remove that headers! The content length is in bytes. Do not try to calculate it by yourself. It is definitly wrong in this example! A Mime-Type with major type text is not binary!
Ok this entire time it was a spacing issue. My file name was "file name.csv" and this works in every browser except firefox. Soon as I put my file name to "filename.csv with no spaces it downloaded it find. I didn't notice that when it was downloading it was only downloading the first part of the name before the space.
In the future make sure the filename has a single quote around it in the header. This will allow Firefox to download it correctly(without stripping off anything past the space) if you need a space the file name.
Good luck!
Add the content-type header with value text/csv
response.setHeader("Content-type: text/x-csv");
Response.AddHeader("content-disposition", string.Format("attachment;filename=\"{0}\"", fileName));
Response.ContentType = "text/csv; charset=utf-8";
I am not expert in Java/JSP but are you sure this is correct for text/csv?
response.setHeader("Content-Transfer-Encoding", "binary");
Did you try commenting out this? In PHP I will simply echo/print the CSV preceded with headers content-type headers and disposition type.

Categories

Resources