不能使用AJAX响应作为文件名(不是内容)

时间:2012-10-26 16:40:44

标签: java jquery ajax servlets

我向servlet发送$.post请求,发送一些需要保存在文件中的数据。 servlet保存数据,然后将路径发送回文件。我试图在方法的回调中导航到response所持有的路径,但是这是正在发生的事情:

function saveData(){
    var path;

    $.post("SaveFileServlet", {data : JSON.stringify(jsonPieces)}, function(response) {
        path = response; // setting the path like this does NOT WORK - nothing happens           
        //path="storing/csv_uploads/test.csv"; // setting the path like this WORKS        

        alert (path); // shows: storing/csv_uploads/filename.csv - e.g. WHAT IT SHOULD

        $("body").append("<iframe src='" + path + "' style='display: none;' ></iframe>");       
    });        
}   

如何使其工作,为什么它不起作用? 感谢。

甚至更新的编辑

GOT IT !!!!! ...这是servlet:它可能没有创建文件:真正的路径不是filename.csv而是System.currentTimeMillis()+".csv"然后我把它写到服务器上。但我只是在创建文件后发送响应(或者我?)......

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    response.setContentType("text/plain");
    response.setCharacterEncoding("UTF-8");
    String filename = "storing/csv_uploads/"+System.currentTimeMillis()+".csv";
    //String filename = "storing/csv_uploads/filename.csv"; //this works since it was previously there
    PrintWriter out = response.getWriter();

    try {
        Type type = new TypeToken<List<PieceFeeder>>(){}.getType();
        ArrayList<PieceFeeder> pieceFeeders = new Gson().fromJson(request.getParameter("data"), type);            

        DataManager dm = new DataManager();
        if (dm.exportPieces(pieceFeeders, filename)) {
            System.out.println("in SaveFileServlet: after exportPieces");
            File f = new File(filename);
            while (!f.exists()) {
                //waiting...I NEVER GET IN HERE
                System.out.println("in SaveFileServlet: waiting for file to exist");
            }
            out.write(filename);
        } else {
            out.write("error at creating file");
        }
    }...
}

DataManager.exportPieces

public void exportPieces(ArrayList<PieceFeeder> pieceFeeders, String filename) {
    BufferedWriter bufferedWriter = null;
    try {
        bufferedWriter = new BufferedWriter(new FileWriter(filename));

        //write first line without "\n"
        if (pieceFeeders.size() > 0) {
            PieceFeeder pf = pieceFeeders.get(0);
            Piece p = pf.getPiece();
            bufferedWriter.write(p.getDescription() + ","
                    + pf.getStock() + ","
                    + p.getLength() + ","
                    + p.getWidth() + ","
                    + p.getLengthEdges() + ","
                    + p.getWidthEdges());
        }
        for (int i = 1; i < pieceFeeders.size(); i++) {
            PieceFeeder pf = pieceFeeders.get(i);
            Piece p = pf.getPiece();
            bufferedWriter.write("\n" + p.getDescription() + ","
                    + pf.getStock() + ","
                    + p.getLength() + ","
                    + p.getWidth() + ","
                    + p.getLengthEdges() + ","
                    + p.getWidthEdges());
        }
        return true;
    } catch (Exception ex) {
        Logger.getLogger(DataManager.class.getName()).log(Level.SEVERE, null, ex);
        return false;
    } finally {
        //Close the BufferedWriter
        try {
            if (bufferedWriter != null) {
                bufferedWriter.flush();
                bufferedWriter.close();
                System.out.println("in exportPieces: finally"); 
            }
        } catch (IOException ex) {
            Logger.getLogger(DataManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

我总是得到

"in exportPieces: finally"

"in SaveFileServlet: after exportPieces"

并且永远不会调用"in SaveFileServlet: waiting for file to exist" 所以在发送响应之前文件存在

但如果我发送一个旧文件*一个尚未创建的文件,则可以正常工作

较新的修改

只是为了说清楚:如果我这样做:

  • window.location = path
  • $("body").append("<iframe src='" + path + "' ></iframe>");删除了display:none 它会显示404 errorThe requested resource () is not available.,但标题显示我正在尝试访问:http://localhost:8080/optimizerwithservlet/storing/csv_uploads/filename.csv所以它就在那里

修改

当用户sugeested我安装了Firebug,这就是我得到的:

<iframe style="display: none;" src="storing/csv_uploads/filename.csv">

意思是它有效!但为什么不显示......?

旧编辑:

如果这可能很重要,虽然我对此表示怀疑:这是来自servlet的相关代码片段:

    response.setContentType("text/plain");
    response.setCharacterEncoding("UTF-8");
    String filename = "storing/csv_uploads/filename.csv";
    PrintWriter out = response.getWriter();
    out.write(filename);    

4 个答案:

答案 0 :(得分:3)

$.post是异步的。您试图在值存在之前提醒该值,即所有。

来自jQuery API documentation

  

Ajax中的第一个字母代表“异步”,意思是   操作并行发生,完成顺序不是   保证。 $ .ajax()的async选项默认为true,表示   在发出请求后代码执行可以继续。设置   此选项为false(从而使调用不再异步)   强烈劝阻,因为它可能导致浏览器成为   不响应。

答案 1 :(得分:0)

编辑:您可能需要将dataType指定为“text”以确保字符串返回。

在回调中,假设response是一个字符串,您只需执行:

window.location = response;

这会将浏览器重定向到响应指示的路径,假设它是绝对URL或root-relative(即以/)开头。

答案 2 :(得分:0)

和Claudia:

您是否绝对确定您从servlet获得的响应是​​一个简单的字符串与您的路径?周围没有任何空白或类似的东西吗?如果不确定,请尝试将dataType设置为text

我的建议是,在您的页面中添加<iframe>,并将src属性设置为您的文件下载路径。确保您甚至能够访问该文件。这至少会排除它是否是相对路径问题。

不使用alert(),而是使用console.log() - 因为console.log()会保留数据结构并让您正确查看。

修改

function saveData(){
    var path;

    $.post("SaveFileServlet", {dataType: 'text', data : JSON.stringify(jsonPieces)}, function(response) {
        path = response; // setting the path like this does NOT WORK - nothing happens           

        console.log (path); 

        $("body").append("<iframe src='" + path + "' style='display: none;' ></iframe>");       
    });        
}   

答案 3 :(得分:-1)

问题是执行顺序。正如登录指出的那样,ajax调用是异步的,因此浏览器会在等待结果时继续执行操作。

这是最基本的:

function doSomething() {
    $.post("SaveFileServlet", {data : JSON.stringify(jsonPieces)}, function(response) {
      alert('post done');
    }
    alert('doSomething done');
}

几乎100%的时间,您将获得的第一个警报将是“完成任务”而不是“完成后”。

这是因为JavaScript没有等待ajax调用完成以继续下一步。