【问题标题】:DataTable to csv file数据表到 csv 文件
【发布时间】:2022-01-04 20:18:06
【问题描述】:

我使用 bootstrap/thymeleaf 创建了一个网页,其中显示了一些使用 Ajax 的数据表。我有导出到 CSV 的按钮,但我需要的是从这个数据表生成一个临时文件,并在数据表已经使用按钮加载数据时获取到我的控制器的路径。

所以我需要一种方法来创建一个新函数,但我真的不知道该怎么做。可能不需要再次调用我的 sql 存储库,因为表非常大。

JavaScript 代码

function mostrarMaticulaEstudiant(data) {

    var url = "/9avaldoval/administracio/cercarMaticulaEstudiant?idEdicio=" + data;
    dataTableMatriculaEstudiant(url);
}

function dataTableMatriculaEstudiant(url) {

    var columns;
    var columnsConfig;
    var columnsFiltres;

    columns = crearColumnesTaulaMatriculaEstudiant();
    //columnsConfig = configurarColumnaBotonsEstudis(columns.length);
    var sorting = [[0, "asc"]];

    var htmlTable = crearTaulaHtmlMatriculaEstudiant(14);

    $('#divTaula').html(htmlTable);


    var table = $('#taulaMatriculaEstudiant').DataTable({
        scrollX: true,
        processing: false,
        ajaxSource: url,
        fnServerData: function(sSource, aoData, fnCallback) {
            aoData = $("#formAdmBlue").serializeArray();
            $.ajax({
                "dataType": 'json',
                "type": "POST",
                "url": sSource,
                "data": aoData,
                "success": fnCallback
            });
        },

        columns: columns,
        columnDefs: columnsConfig,
        sorting: sorting,
        language: {
            "lengthMenu": "Mostra _MENU_ files per pàgina",
            "search": "Filtre: ",
            "zeroRecords": "Sense resultats",
            "info": "Pàgina _PAGE_ de _PAGES_",
            "infoEmpty": "Files no trobades a la cerca",
            "infoFiltered": "(filtrat de _MAX_ files totals)",
            "sProcessing": "<img src='/9avaldoval/img/loading_gear.gif' width='48px' height='48px'>",
            "paginate": {
                "next": "<span class='oi oi-chevron-right'></span>",
                "previous": "<span class='oi oi-chevron-left'></span>"
            }
        },
        dom: "<'row'<'col-sm-12 col-md-4'B><'col-sm-12 col-md-4'l><'col-sm-12 col-md-4'f>>" +
            "<'row'<'col-sm-12'tr>>" +
            "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
        buttons: ['copy', 'excel', 'pdf'],
        error: function() {
            alert("No s'ha pogut obtenir la informació");
        }
    });


}


function crearTaulaHtmlMatriculaEstudiant(numColumnes) {

    var htmlTableOpen = '<table style="width: 100%;" cellpadding="0" cellspacing="0" border="0" class="table table-hover" id="taulaMatriculaEstudiant"><thead>';

    var htmlTableHeaderRow = '<tr>';
    var htmlTh = '<th></th>';
    for (var i = 0; i < numColumnes; i++) {
        htmlTableHeaderRow = htmlTableHeaderRow + htmlTh;
    }
    htmlTableHeaderRow = htmlTableHeaderRow + '</tr>';
    var htmlTableClose = '</thead></table>';
    var htmlTable = htmlTableOpen + htmlTableHeaderRow + htmlTableClose;
    return htmlTable;

}


function crearColumnesTaulaMatriculaEstudiant() {


    var columns = [];
    columns.push({ "sTitle": "IdAssigEdicio", "mData": "IdAssigEdicio", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "IdEdicio", "mData": "IdEdicio", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "IdCodiassigPare", "mData": "IdCodiassigPare", "sWidth": "10%", "className": "text-center", "defaultContent": "" });
    columns.push({ "sTitle": "IdUsuariUPF", "mData": "IdUsuariUPF", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "IdCodiAssigFill", "mData": "IdCodiAssigFill", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "IdAssigFill", "mData": "IdAssigFill", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "EsRepetidor", "mData": "EsRepetidor", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "CodiCentreEstudiant", "mData": "CodiCentreEstudiant", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "CentreEstudiant", "mData": "CentreEstudiant", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "EstudiEstudiant", "mData": "EstudiEstudiant", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "CodiEstudiEstudiantL", "mData": "CodiEstudiEstudiantL", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "DescEstudi_es", "mData": "DescEstudi_es", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "DescEstudi_en", "mData": "DescEstudi_en", "sWidth": "10%", "defaultContent": "" });
    columns.push({ "sTitle": "DescEstudi_ca", "mData": "DescEstudi_ca", "sWidth": "10%", "defaultContent": "" });

    return columns;
}

控制器

@RequestMapping(value = "cercarMaticulaEstudiant", params = "idEdicio")
    public @ResponseBody byte[] cercarMaticulaEstudiant(@RequestParam("idEdicio") String idEdicio, Model model)
            throws UnsupportedEncodingException, ParseException {

        log.debug("***** cercarEdicions AJAX ****");

        byte[] dataTableSource = null;
        List<BlueMatriculaEstudiant> llistaMatriculaEstudiants;

        llistaMatriculaEstudiants = blueMatriculaEstudiantService
                .cercarBlueMatriculaEstudiant(Integer.parseInt(idEdicio));

        dataTableSource = operacionsService.blueMatriculaEstudiantsToJson(llistaMatriculaEstudiants);

        return dataTableSource;
    }

HTML/引导程序

<div class="col-lg-12" 
                        style="margin-bottom: 40px;">
                        <br>
                        <div class="card">
                            <h5 class="card-header" th:id="llistat"
                                data-th-text="#{administracio.blue.llistat}"></h5>
                            <div class="card-body">
                                <div class="row"
                                    style="padding-left: 10px; padding-right: 10px;">
                                    <div class="col-md-12">
                                        <div id="divTaula"></div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

【问题讨论】:

    标签: javascript java bootstrap-4 thymeleaf


    【解决方案1】:

    我认为最简单的方法是在客户端使用 JS 创建csv 文件。

    首先,您需要从DataTabletheir documentation shows it could be done like this 获取数据:

    let table = $('#taulaMatriculaEstudiant').DataTable()
     
    let data = table
        .rows()
        .data()
    

    现在,csv 格式基本上是一种带有分隔符的文本格式。因此,您需要遍历 data 中的行并合并单元格以分隔文本行,如下所示:

    let text = '';
    data.map( row => text += row.join( ';' ) + '\n' ) // replace ';' with your preferred CSV separator
    

    然后您只需要创建一个文档并下载它。为此,我建议使用filesaver.js:

    let blob = new Blob( [text], {type: "text/csv;charset=utf-8"} )
    saveAs( blob, 'taulaMatriculaEstudiant.csv' ) // any name with CSV extension
    

    请注意,我从未使用过DataTables,所以我可能会误解它在.rows().data() 之后从表中返回数据的数据结构(我假设它返回一个数组表示行中单元格的数组)。一般的做法应该是正确的。

    编辑

    但是我不建议将数据从浏览器发送到服务器 - 只需在服务器端创建正确的文件。例如。像这样:

    @Controller // note it's not @RestController
    public class CsvController {
        private CommonDataService dataService; // service with your table data logic. Don't forget to add @Service to it
    
        @GetMapping( "/csv/example" )
        public void exampleCsv( HttpServletResponse response ) throws IOException {
            byte[] processedFile = dataService.getTaulaMatriculaEstudiant(); // prepare your data the same way as your main data controller and create the csv table the way you like it
    
            ContentDisposition disposition = ContentDisposition.builder( "attachment" )
                .filename( "taulaMatriculaEstudiant.csv", StandardCharsets.UTF_8 )
                .build();
            response.setContentType( "text/csv" );
            response.setHeader( "Cache-Control", "no-cache" );
            response.setHeader( "Expires", "0" );
            response.setHeader( "Pragma", "no-cache" );
    
            IOUtils.copy( new ByteArrayInputStream( processedFile ), response.getOutputStream() ); // IOUtils from Apache Commons-IO
        } 
    
        @Autowired
        public void setDataService( CommonDataService dataService ) {
            this.dataService = dataService;
        }
    }
    

    【讨论】:

    • 我理解它并且我让它工作,但是有什么方法可以使用户不可见下载或使这个文件临时?因为我想在用它做另一件事后删除文件,但不会被用户看到
    • 我认为最好的方法是在不抓取客户端表的情况下在服务器端准备数据。例如。您可以创建一个新的@Controller(最好不要使用REST)GET-request 方法,该方法将使用与cercarMaticulaEstudiant() 相同的逻辑来准备信息。然后只需处理它并创建您需要的文件,然后将其返回给用户。无需来回发送数据。我将通过有关如何下载文件的说明来扩展我的答案。但是,您可以使用 JS 的 FileReader 将您的 blob 转换为 Base64 字符串,并在绝对必要时通过 AJAX 发送。
    • 好的,我会研究一下,但不需要创建新服务吧?我仍然可以使用 blueMatriculaEstudiantService 作为我的数据服务还是会出现问题?
    • 是的,当然,我只是用它作为代码抽象的例子(在这两种情况下你都可以使用相同的逻辑来获取数据)
    • 这对我来说很新,有些东西我不明白,所以这个文件将保存在哪里?或者我怎样才能得到路径。还有就是用完怎么删除还是自动删除
    猜你喜欢
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 2021-05-08
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多