0

I have a file txt on the server (previously generated). When user clicks on button it generates the file, now I want (additionally) download the file inside my function. But I can't make it work(I'm new on JAVA EE), cause I don't know how to get HttpServletResponse.

From web I call function with this:

@Path("getreport")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public JSONObject getreport(CommonInput input) {
    JSONObject j = objectmapper.conertValue(reportBean.getreport(),JSONObject.class);
    return j;
}

reprotBean has function:

public void getreport() {
    //...doing many things
    //generating my file
    List<String> lines = new ArrayList<>();
    lines.add("star file");
    //..adding many lines
    Path file = Paths.get("C:\\Users\\myuser\\file.txt");
    Files.write(file, lines, StandardCharsets.UTF_8);

    downloadFile();
    //...doing many things
}

I found this way to download my file:

public void downloadFile(HttpServletResponse response){ 
    String sourceFile = ""C:\\Users\\myuser\\file.txt"";
    try {
        FileInputStream inputStream = new FileInputStream(sourceFile);
        String disposition = "attachment; fileName=outputfile.txt";
        response.setContentType("text/txt");
        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);
    }
}

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;
}
}

When I try to use downloadFile(), it requires HttpServletResponse, and I don't have that parameter. I can't understand how to get that (how it works), or do I have to use another method for download my file?

All solutions I found requires HttpServletResponse (download files from browsers)

Vrian7
  • 588
  • 2
  • 6
  • 14
  • Possible duplicate of https://stackoverflow.com/questions/12239868/whats-the-correct-way-to-send-a-file-from-rest-web-service-to-client – Ezequiel Aug 07 '19 at 20:51
  • Not at all, I don't want to return file as response, I want additionally download file on browser, cause function actually returns data. – Vrian7 Aug 07 '19 at 20:59

1 Answers1

0

If you have that file generated already. Just need write it to HttpServletResponse

        resp.setContentType("text/plain");
        resp.setHeader("Content-disposition", "attachment; filename=sample.txt");

        try(InputStream in = req.getServletContext().getResourceAsStream("sample.txt");
          OutputStream out = resp.getOutputStream()) {

            byte[] buffer = new byte[ARBITARY_SIZE];

            int numBytesRead;
            while ((numBytesRead = in.read(buffer)) > 0) {
                out.write(buffer, 0, numBytesRead);
            }
        }

Be sure to make your file to be accessed by ServeletContext

If you are using Spring Rest framework. Can refer to below

    @GetMapping("/download")
    public ResponseEntity<byte[]> downloadErrorData() throws Exception {
        List<Employee> employees = employeeService.getEmployees();
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(employees);
        byte[] isr = json.getBytes();
        String fileName = "employees.json";
        HttpHeaders respHeaders = new HttpHeaders();
        respHeaders.setContentLength(isr.length);
        respHeaders.setContentType(new MediaType("text", "json"));
        respHeaders.setCacheControl("must-revalidate, post-check=0, pre-check=0");
        respHeaders.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
        return new ResponseEntity<byte[]>(isr, respHeaders, HttpStatus.OK);
    }

credit to: https://www.jeejava.com/file-download-example-using-spring-rest-controller/

Qingfei Yuan
  • 1,196
  • 1
  • 8
  • 12
  • That's the problem, where can I get HttpServletResponse (I don't understand)? Should I get from context? should I create a new instance? – Vrian7 Aug 07 '19 at 21:20
  • 1
    No, you never need create a new instance by yourself. It should be offered by your framework context. Seems you are using Spring Rest. You still can use similar way to achieve it. – Qingfei Yuan Aug 07 '19 at 21:23