简体   繁体   English

如何从 Java ByteArrayResource 下载 JS 中的 excel 文件

[英]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.我正在尝试在 Web 应用程序中添加一个按钮,以允许我的同事下载 excel 文件。

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?如何将 byteArrayResource 转换为 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.这是在动态页面中,js 代码用于组件。 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我对 Spring 和 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?编辑:我在 Spring 中打印了 file.length() ,它与 JS 中的 res.length 不同,后者的值较小,可能是什么原因?

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).我会将ByteArrayResource更改为FileSystemResource ,它在其构造函数中采用path并允许将文件流式传输到响应,而不是先将其读入内存(这可能会导致服务器上出现内存问题)。

In your client code link directly to the backend instead of downloading it into JavaScript using plain HTML:在您的客户端代码中直接链接到后端,而不是使用纯 HTML 将其下载到 JavaScript:

<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.无需先将其缓冲到 JS 中,让浏览器和服务器负责协商下载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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