简体   繁体   中英

How to download excel file in JS from Java ByteArrayResource

Im trying to add a button in a web app that alloww my colleagues to download excel files.

In the back:

public String getInvoiceList(String invoiceNumber) {
    System.out.println("invoice number : " + invoiceNumber);
    //Recursively list all files
    List<Path> pathList = new ArrayList<>();
    //The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner.
    try (Stream<Path> stream = Files.walk(Paths.get(SERVER_LOCATION))) {
        System.out.println("WE ARE IN");
        pathList = stream.map(Path::normalize)
                .filter(Files::isRegularFile) // directories, hidden files and files without extension are not included
                .filter(path -> path.getFileName().toString().contains(invoiceNumber))
                .filter(path -> path.getFileName().toString().endsWith(EXTENSION))
                .collect(Collectors.toList());
    }
    catch(IOException e) {
        e.printStackTrace();
    }
    if(pathList.isEmpty()) {
        System.out.println("NO INVOICE FILE FOUND : " + invoiceNumber);
        return null;
    }
    else {
        pathList.forEach(System.out::println);
        return pathList.get(0).toString();
    }
}
@GetMapping(value = "/downloadInvoiceExcel")
public ResponseEntity<Resource> download(@RequestParam("invoiceNumber") String invoiceNumber) throws IOException {

    String filename = getInvoiceList(invoiceNumber);
    File file = new File(filename);

    System.out.println("filename : " + file);

    HttpHeaders header = new HttpHeaders();
    header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+filename);
    header.add("Cache-Control", "no-cache, no-store, must-revalidate");
    header.add("Pragma", "no-cache");
    header.add("Expires", "0");

    Path path = Paths.get(file.getAbsolutePath());

    System.out.println("Absolute Path : " + path);
    ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));

    return ResponseEntity.ok()
            .headers(header)
            .contentLength(file.length())
            .contentType(MediaType.parseMediaType("application/octet-stream"))
            .body(resource);
}

How do I convert the byteArrayResource to a file in JS?

I tried this in the front end

There's button that calls this fonction after I selected the files I want to download

This is in a dynamic page and the js code is for the component. So no imports possible.

invoiceDownload() {
    for(let i of that.table.selectionRows) { //we go through all the elements with selected
        let invoice_number = i["invoice_number"]; // we get the value of the field we want
    let param = {invoiceNumber: invoice_number};
    getAction('/shippingInvoice/downloadInvoiceExcel', param) // goes to backend to get the file
    .then(res=> {
        let filename = "Invoice N°" + invoice_number + ".xlsx";
     
            var buf = new ArrayBuffer(res.length);
            var view = new Uint8Array(buf);
            for (var i=0; i!=res.length; ++i) view[i] = res.charCodeAt(i) & 0xFF;
      
            var blob = new Blob([buf], {
                type: "application/octet-stream"
            });
            var link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = filename;
            link.click();
        });
    }
}

But the the data is corrupted

I'm very new to Spring and JS

EDIT: I printed file.length() in Spring and it's different to res.length in JS which value is smaller, what could be the reason?

I would change ByteArrayResource to FileSystemResource , which takes the path in its constructor and will allow the file to be streamed to the response, instead of reading it into memory first (which could result in memory issues on the server).

In your client code link directly to the backend instead of downloading it into JavaScript using plain HTML:

<a href="/shippingInvoice/downloadInvoiceExcel?invoiceNumber=...">Download Excel Invoice</a>

There is no need to buffer it into JS first, let the browser and server take care of negotiating the download.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM