Servlet响应包含文本(用于显示)以及文件下载
Servlet-Response containing text (for display) as well as file download
我正试图通过Java Servlet从服务器下载一个文件。我遇到的问题是,当我直接输入servlet url时(https://localhost:8443/SSP/settings?type=db_backup)我让servlet执行它的代码,并用下载对话框提示我。
但我想通过Javascript调用servlet 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:
我发现$.get()
函数中的data
填充了所需文件的内容。例如,我现在可以在div中显示.txt文件的内容,但我想不加载所说的.txt文件。
编辑2:
解决了它,请参阅下面我的答案了解详细信息&comment/ansewer如果您认为可以用更好的方式完成
经过一段时间的努力,我找到了一个有效的解决方案。也许还有更好的,但这就是我想出的。
希望这对其他人也有帮助。
我在这里所做的基本解释:
- 让一个表单(通过JS)向javaservlet发出GET请求
- servlet执行一个命令行脚本(在我的例子中是postgreSQL数据库的sql转储)
- servlet收集命令行的输出和生成的文件(sql_dump)的内容,并将它们放入响应中
- 客户端获取响应并将其分为三部分(命令行输出、sql_dump-file的文件名和内容)
- 然后(通过JS)命令行输出显示在文本区域中,以便更好地了解脚本的实际操作
- sql_dump-file的内容由JS Code处理以生成要下载的文件(通过按钮手动或自动)
因此,事不宜迟,这里我们使用流。。。代码:)
解决方案:
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 Servlet:
@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转储包含"小写"&我不得不替换的"大写"引号。我把每一个链接都放在这里,以防有人也与他们斗争。它们对那里列出的那些字符有多个编码。
Unicode字符"双低位-9引号"(U+201E)
Unicode字符"左双引号"(U+201C)
- 如何在生成下载文件时显示加载动画
- 选择文件后显示图像
- 我想在选择输入文件上显示图像
- asp.net网站文件下载历史记录
- Firefox,如何提交表单触发文件下载,但停留在网页上
- 从javascript文件中获取JSON,并使用NodeJS在路由文件中显示
- Interent Explorer中的数据URI文件下载
- 将页面上的文本替换为 jQuery 并提示文件下载
- Javascript/AJAX 自动在文本文件中显示文本
- HTML表单返回并下载文件时显示进度掩码
- 在angularjs中下载文件时显示下载进度文本
- 点击链接并下载文件后显示弹出窗口
- AngularJS -显示加载图标,直到csv文件下载
- 如何在下载文件之前显示警告
- 是否有可能不允许iframe显示文件下载弹出
- 为什么IE在GWT中不显示PDF文件下载对话框?
- 强制文件下载而不是显示在浏览器中
- Servlet响应包含文本(用于显示)以及文件下载
- 下载一个大文件或显示错误
- Javascript:如何在文件下载之前显示旋转器