问题描述
我有一个从 JSP 调用的长时间运行的 servlet 进程。
我想将 servlet 进程的状态发送给客户端。
除了流媒体部分,我的一切都按照我想要的方式工作。
我正在使用 ajax 调用 servlet 并用响应填充文本区域。但是,响应会在最后一次性发送到客户端,而不是逐步流式传输。
我希望客户看到每个响应 (flush()) 发生时,而不是在调用结束时立即查看。
Ajax 调用:
postUploadFile = function() {
$("#status").val("");
YES.getAndShowStatus("status","${home}/Upload");
}
YES.getAndShowStatus = function(listenerId,url,successFunction) {
jQuery.get(url,function(data) {
val = jQuery("#" + listenerId).val();
jQuery("#" + listenerId).val(val + data);
}
);
};
Servlet 代码:
@Override
protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
log.info("----------");
log.info("Doing post");
resp.setContentType("text/plain");
OutputStream out = resp.getOutputStream();
out.write("FOOBAR 1\n".getBytes());
out.flush();
out.write("FOOBAR 2\n".getBytes());
out.flush();
out.write("FOOBAR 3\n".getBytes());
out.flush();
log.info("Done.");
}
我最终得到了这个,但没有看到它发生时的进展。我需要做什么才能看到进度?
解决方法
此问题中发布的原始代码存在一个大问题和一些小问题。最大的问题是这一行:resp.setContentType("text/plain");
。将此行更改为 resp.setContentType("application/text");
修复了服务器端的流式传输问题。对客户端代码进行了更实质性的更改。下面的代码有效并且是一个完整的工作解决方案,用于将多部分表单发布到服务器并在它发生时从服务器获取流响应(几个值是硬编码的,需要清理但它可以完成工作)。
服务器代码:
@Override
protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
log.info("----------");
log.info("Doing post");
resp.setContentType("application/text");
OutputStream out = resp.getOutputStream();
out.write("Writing file to server".getBytes());
out.flush();
writeZipFileToDisc(req,resp);
out.write("\n\nDone.\n".getBytes());
out.flush();
log.info("Done.");
}
客户代码:
postUploadFile = function() {
$("#status").val("");
YES.getAndShowStatus("status","${home}/Upload");
}
YES.getAndShowStatus = function(listenerId,url,successFunction) {
// based on https://gist.github.com/sohelrana820/63f029d3aa12936afbc50eb785c496c0
var form = $("#uploadForm")[0];
var data = new FormData(form);
$.ajax({
type: "POST",enctype: 'multipart/form-data',url: url,data: data,processData: false,contentType: false,cache: false,xhrFields: {
// Getting on progress streaming response
onprogress: function(e)
{
var progressResponse;
var response = e.currentTarget.response;
val = jQuery("#" + listenerId).val();
jQuery("#" + listenerId).val(response);
}
}
});
};