【问题标题】:Detect and report completed downloads in Java在 Java 中检测并报告已完成的下载
【发布时间】:2015-09-14 19:25:25
【问题描述】:

我正在开发一个网络应用程序 (Java/JSP),其中一部分是允许用户仅“一次”下载请求的文件。当他们点击“下载”按钮时,他们将被要求保存/打开或取消文件并且他们响应的文件将被标记为已下载并且用户将无法再次下载它的问题。 我正在尝试找出一种方法,当用户回复“取消”时不将文件计为已下载文件,并检查用户是否真的完全下载了文件。

这里是Java部分:

@WebServlet("/download")
    public class download extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final int DEFAULT_BUFFER_SIZE = 10240;
/**
 * @see HttpServlet#HttpServlet()
 */
public download() {
    super();
    // TODO Auto-generated constructor stub
}

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
 *      response)
 */
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    try {

        Class.forName("org.sqlite.JDBC");
        Connection c = DriverManager.getConnection("jdbc:sqlite:C:\\sqlite\\mascapp.db");
        c.setAutoCommit(false);
        Cookie[] cookies = request.getCookies();
        if(request.getSession().getAttribute("aeid") == null || request.getSession().getAttribute("uid") == null)
        {
            response.sendRedirect("/index.jsp");
        }
        int ae_num = Integer.parseInt(request.getSession().getAttribute("aeid").toString());




        String sql = "SELECT file, filename FROM reports INNER JOIN download USING(tipid) WHERE reports.tipid = ?"+
                "AND download.ts_" + ae_num+ " = 0;";

        PreparedStatement stmt = c.prepareStatement(sql);
        String tipNum = request.getParameter("tipid");
        if (tipNum != null) {

            stmt.setString(1, tipNum);
            //stmt.setString(2, tipNum);
            ResultSet res = stmt.executeQuery();
            BufferedInputStream fileBlob = null;
            String filename = "";

            while (res.next()) {
                fileBlob = new BufferedInputStream(res.getBinaryStream("file"), DEFAULT_BUFFER_SIZE);

                filename = res.getString("filename");
            }
            if (fileBlob != null) {
                System.out.println(filename);
                response.setContentType("APPLICATION/OCTET-STREAM");
                response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

                BufferedOutputStream output = new BufferedOutputStream(response.getOutputStream(),
                        DEFAULT_BUFFER_SIZE);

                byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
                int length;
                while ((length = fileBlob.read(buffer)) > 0) {
                    output.write(buffer, 0, length);
                }

                output.close();
                fileBlob.close();
                Date now = new Date();

                sql = "UPDATE download SET ts_" + ae_num + " = " + now.getTime() + " WHERE tipid = ?;";
                System.out.println(sql);
                stmt = c.prepareStatement(sql);
                stmt.setString(1, tipNum);

                stmt.executeUpdate();
                stmt.close();

                c.commit();
                c.close();
            }
            else
            {

                c.close();
                response.sendRedirect("/MASC/formdownloaded.jsp");

            }
        }
        else
        {
            response.getWriter().append("<html><body><h1>Error: no param</h1></body></html>");
            c.close();

        }
    } catch (SQLException | ClassNotFoundException e) {
        e.printStackTrace();

    }
}

/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
 *      response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
}

}

任何解决方案或建议?!提前谢谢你。

【问题讨论】:

  • 我认为你最好的办法是尝试检测并报告成功的下载,并使用这些报告来告知用户是否已经下载了文件。否则如果用户下载中断怎么办?不过,恐怕我没有具体的建议来说明如何做到这一点。无论如何,试图强制你的用户是一个糟糕的计划。不太可能被欣赏。
  • 我已经更新了这个问题,我同意你的看法。如何跟踪用户按下“取消”或“下载”?!
  • 在有限的时间内允许下载任意次数可能比只允许下载一次更容易。根据您的用例可能就足够了。

标签: java servlets


【解决方案1】:

查看此页面:http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/(此链接有时不起作用,如果您对它有问题,这里是 github 的链接:https://github.com/johnculviner/jquery.fileDownload)。

看起来您在这里可以做的最好的事情是通过检查从服务器发送回的带有下载文件流的客户端特殊 cookie 来确保下载已开始。为此,您必须像在这个线程中一样将 Cookie 添加到 servlet 响应中: Set cookie only after file download complete.

所以在你的 servlet 中 doGet 方法的末尾你应该有类似的东西:

Cookie fileDwnld = new Cookie("fileDownload", "true");
fileDwnld.setPath("/");
response.addCookie(fileDwnld);

这是客户端代码:

<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="jquery.fileDownload.js"></script>
<script>
$(document).ready(function() {
    $("#btnSubmit").click(function(){
        $.fileDownload('path/to/servlet')
            .done(function () { alert('File download a success!'); })
            .fail(function () { alert('File download failed!'); });
    }); 
});

【讨论】:

    【解决方案2】:

    答案是不要那样做。这些对话框的存在是有充分理由的,其中一些涉及安全性。

    您想要做什么取决于为什么您只希望用户下载文件一次。下载可能由于各种原因而失败,那么如果用户在下载过程中失去连接,你会怎么做?

    【讨论】:

    • 这是我的问题的一部分,我一般如何在 webapp 中使用 JAVA 从数据库 (Sqlite) 跟踪下载的文件,以了解用户是否真的完全下载了文件?!
    【解决方案3】:

    我没有正确的答案,但我知道“附件;”如果您理解我的意思,与“打开它”相比,在标题中强制浏览器“下载”文件。尝试删除该标头,看看是否获得所需的效果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-02
      • 2012-01-30
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 2022-10-19
      • 2011-10-28
      • 1970-01-01
      相关资源
      最近更新 更多