Servlet-Response包含文本(用于显示)以及文件下载

时间:2016-08-02 13:40:39

标签: javascript jquery html5 tomcat8

我试图通过Java Servlet从我的服务器下载文件。 我遇到的问题是,当我直接输入servlet url(https://localhost:8443/SSP/settings?type=db_backup)时,我得到servlet来执行其代码并通过下载对话框提示我。

但我想通过Javascript调用servlets的doGet方法,用一些进度条包装它。

此处出现问题:servlet中的代码已执行但我没有获得该文件的下载提示。

我的代码到目前为止:

HTML:

<!-- Solution #1 -->
<button class="btn_do_db_backup" type="button">DB-Backup #1</button>

<!-- Solution #2 -->
<form action="/SSP/settings?type=db_backup" method="GET">
    <button type="submit">DB-Backup #2</button></br>
</form>

JS:

// Solution #1
$(".btn_do_db_backup").click(function(e){
    e.preventDefault();
    $.get("settings?type=db_backup", function(data){
        if(data != ""){
        //further coding
        }
    });

    // Having the code below works but doesnt
    // give me the chance to wrap the call with a loading animation

    //document.location = "/SSP/settings?type=db_backup";
});

的Servlet

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    // PART 1 
    // execute srcipt to generate file to download later on

    StringBuffer output = new StringBuffer();
    ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "D:\\TEMP\\sql_dump.cmd");
    builder.redirectErrorStream(true);
    Process p = builder.start();
    BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line = "";
    String filename = "";
    int tmp = 0;
    while (true) {
        line = r.readLine();
        if (line == null) { break; }
        output.append(line + "\n");
        // code for finding filename not optimal but works for now -> redo later on
        if(tmp == 1){
            filename = line.substring(line.indexOf("db_backup_"), line.indexOf('"', line.indexOf("db_backup_")) );
        }
        tmp++;
    }

    // PART 2
    // download the file generated above

    OutputStream out = response.getOutputStream();
    String filepath = "D:\\TEMP\\sql_dump\\";

    response.setContentType("APPLICATION/OCTET-STREAM");
    response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");

    FileInputStream fileInputStream = new FileInputStream(filepath + filename);

    int i;
    while ((i = fileInputStream.read()) != -1) {
        out.write(i);
    }

    out.close();
    fileInputStream.close();
}

解决方案#2效果很好,我得到一个弹出窗口来下载文件。

解决方案#1调用servlet doGet方法(通过上面的JS代码,我的servlet中的代码正确执行)但我没有下载弹出窗口

我想使用解决方案#1,因为这让我有机会用加载动画包装$.post调用。

在解决方案#1中我缺少什么才能让下载弹出窗口进行购物?

编辑1:

我发现data函数中的$.get()填充了所需文件的内容。我现在可以在div中显示.txt文件的内容,但我想重新载入.txt文件。

编辑2:

解决了它,请参阅下面的答案以获取详细信息。如果您认为可以更好地完成评论/评论

1 个答案:

答案 0 :(得分:0)

经过一段时间试图让它发挥作用后,我找到了一个有效的解决方案。可能会有更好的,但那就是我提出的那个。

希望这对其他人也有帮助。

我在这里做的基本解释:

  • 让表单执行GET-Request(通过JS)到java servlet
  • servlet执行命令行脚本(在我的情况下是我的postgreSQL数据库的sql-dump)
  • servlet收集命令行的输出和生成的文件的内容(sql_dump)并将它们放入响应中
  • 客户端获取响应并将其分为3个部分(命令行输出,文件名和sql_dump文件的内容)
  • 然后(通过JS)命令行输出显示在textarea中,以便更好地概述脚本实际执行的操作
  • sql_dump文件的内容由JS-Code处理,以生成要下载的文件(通过按钮或自动手动删除)


所以不用多说了,这里我们使用 flow ...代码:)

解:

<强> HTML:

<form id="form_download_db_backup">
    <input type="submit" value="Create & Download DB-Backup"></br>
    <a download="" id="downloadlink" style="display: none">download</a>
</form>
<div class="db_backup_result" id="db_backup_result" style="display: none;">
    </br>Commandline-Output</br>
    <textarea id ="txta_db_backup_result" rows="4" cols="50"></textarea>
</div>

<强> JS:

$("#form_download_db_backup").submit(function(e){
    e.preventDefault();
    var spinner = new Spinner().spin();
    var target = document.getElementById('content');
    target.appendChild(spinner.el);
    $.ajax({
        url:'settings?type=db_backup',
        type:'get',
        success:function(data){
            spinner.stop();
            if(data != ""){
                var str_data = "" + data;

                // Cut commanline output from data
                var commandline_output = str_data.substring( 0, str_data.indexOf("--End") );

                //show commanline output in textarea
                $("#txta_db_backup_result").html(commandline_output);

                // Cut content of db_backup file from data
                var sql_dump_content = str_data.substring( str_data.indexOf("--sql_d_s--") + 13,str_data.indexOf("--sql_d_e--") );//|

                // Cut filename from data
                var filename = str_data.substring( str_data.indexOf("--sql_d_fns--") + 15,str_data.indexOf("--sql_d_fne--") - 2 );

                //-------------------------------------------------------------
                // Prepare download of backupfile
                var link = document.getElementById('downloadlink');
                var textFile = null;
                var blob_data = new Blob([sql_dump_content], {type: 'text/plain'});

                // FOR IE10+ Compatibility
                if(window.navigator.msSaveOrOpenBlob) {
                    window.navigator.msSaveBlob(blob_data, filename);
                }

                // If we are replacing a previously generated file we need to
                // manually revoke the object URL to avoid memory leaks.
                if (textFile !== null) {
                  window.URL.revokeObjectURL(textFile);
                }
                textFile = window.URL.createObjectURL(blob_data);
                link.href = textFile;
                link.download = filename;
                //link.style.display = 'block'; // Use this to make download link visible for manual download
                link.click(); // Use this to start download automalically
                //-------------------------------------------------------------

                // show div containing commandline output & (optional) downloadlink
                document.getElementById("db_backup_result").style.display = 'block';
            }
        }
    });
});

<强>的Java小服务程序:

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    String type = request.getParameter("type");

    if(null != type)switch (type) {
        case "db_backup":

            ServletOutputStream out = response.getOutputStream();

            // Prepare multipart response
            response.setContentType("multipart/x-mixed-replace;boundary=End");

            // Start: First part of response ////////////////////////////////////////////////////////////////////////

            // execute commandline script to backup the database
            ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "D:\\TEMP\\sql_dump.cmd");
            builder.redirectErrorStream(true);
            Process p = builder.start();
            BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = "";
            String filename = "";
            int tmp = 0;

            while (true) {
                line = r.readLine();
                if (line == null) { break; }
                // code for finding filename not optimal but works for now -> redo later on
                if(tmp == 1){
                    filename = line.substring(line.indexOf("db_backup_"), line.indexOf('"', line.indexOf("db_backup_")) );
                }
                else{
                    line = line.replace("\u201E", "\'"); // replaces the lowercase " (DOUBLE LOW-9 QUOTATION MARK)
                    line = line.replace("\u201C", "\'"); // replaces the uppercase " (LEFT DOUBLE QUOTATION MARK)
                }
                out.println(line);
                tmp++;
            }

            // End: First part of response ////////////////////////////////////////////////////////////////////////

            // Separator of firt & second part
            out.println("--End");
            out.flush();

            // Add filename in response (name of download file)
            out.println("--sql_d_fns--"); // separator for filename (used to extract filename from response data)
            out.println(filename);
            out.println("--sql_d_fne--"); // separator for filename (used to extract filename from response data)

            // Start: Second part of response ////////////////////////////////////////////////////////////////////////
            out.println("--sql_d_s--"); // separator for content of db-dump (this is the text thats going to be downloaded later on)
            String filepath = "D:\\TEMP\\sql_dump\\";

            FileInputStream fileInputStream = new FileInputStream(filepath + filename);

            int i;
            while ((i = fileInputStream.read()) != -1) {
                out.write(i);
            }
            out.println("--sql_d_e--"); // separator for content of db-dump (this is the text thats going to be downloaded later on)
            // End: Second part of response ////////////////////////////////////////////////////////////////////////

            // End the multipart response
            out.println("--End--");
            out.flush();
            break;
        default:
            break;
    }
}

postgreSQL转储包含&#34;小写&#34; &安培; &#34;大写&#34;我必须替换的引号。我在这里放了一个链接,以防有人和他们挣扎。他们对那里列出的那些角色有多种编码。

Unicode Character 'DOUBLE LOW-9 QUOTATION MARK' (U+201E)

Unicode Character 'LEFT DOUBLE QUOTATION MARK' (U+201C)