论坛首页 Java企业应用论坛

如何跟踪 客户端下载是否完成

浏览 10898 次
该帖已经被评为隐藏帖
作者 正文
   发表时间:2007-11-03  
引用
关键是“客户端下载是否完成”这个怎么理解?是不是当用户把文件完全保存到本地硬盘之后才算下载完成?


不错,客户端下载完成的含义就是用户把文件保存到本地硬盘。
之所以进行这样的定义,是为了更准确地判断出,该点击用户确实是想下载该文件的用户,而不是被误导或是其他不正常原因而导致点击了下载链接。因为后面紧跟着扣费操作!

    如果用户仅仅是点击了下载连接,而取消了下载确认对话框,那么显然,这个用户对该文件不感兴趣,扣费操作是不应该执行的。

    而且,我想知道的是,如果不能准确判断用户是否下载了文件,为什么要用一大堆的代码去 读文件,发文件,而不是用一条 response.sendForward(url),效果不是一样的吗?

0 请登录后投票
   发表时间:2007-11-04  
我认为在不使用ActiveX等客户端下载软件的情况下,使用浏览器链接下载,可能只有上面那位老兄提的下载再索取密码扣费的方式是最准确的,甚至也只有那种办法才能确保用户真正的得到你的软件。
0 请登录后投票
   发表时间:2007-11-04  
这个可以用AJAX实现的吧,当下载完成它会触发一个事件这个时候提醒服务器端扣费
0 请登录后投票
   发表时间:2007-11-04  
这个问题 最好的解决方案就是自己写个简单的httpFile Server这个不难
网上有很多实现,简单的只要一个类就搞定

这样你就可以处理很多事情了

但是就像我前面说的,有一个误差是无法避免的
就是服务器向客户端发送 最后一个字节 之后, 服务端就认为下载完毕,但是这最后一个字节是否传到了客户端 服务器无法知道,除非你再做个特殊的下载软件.
0 请登录后投票
   发表时间:2007-11-04  
/*
 * Java Network Programming, Second Edition
 * Merlin Hughes, Michael Shoffner, Derek Hamner
 * Manning Publications Company; ISBN 188477749X
 *
 * http://nitric.com/jnp/
 *
 * Copyright (c) 1997-1999 Merlin Hughes, Michael Shoffner, Derek Hamner;
 * all rights reserved; see license.txt for details.
 */

import java.io.*;

public class HttpFile implements HttpProcessor {
  protected File file;
  
  public HttpFile (HttpInputStream in) throws IOException {
    if (in.getMethod () == HTTP.METHOD_POST)
      throw new HttpException (HTTP.STATUS_NOT_ALLOWED,
                               "<TT>" + in.getMethod () + " " + in.getPath () + "</TT>");
    file = new File (HTTP.HTML_ROOT, HTTP.translateFilename (in.getPath ()));
    if (in.getPath ().endsWith ("/"))
      file = new File (file, HTTP.DEFAULT_INDEX);
    if (!file.exists ())
      throw new HttpException (HTTP.STATUS_NOT_FOUND,
                               "File <TT>" + in.getPath () + "</TT> not found.");
    if (file.isDirectory ())
      throw new RedirectException (HTTP.STATUS_MOVED_PERMANENTLY,
                                   in.getPath () + "/");
    if (!file.isFile () || !file.canRead ())
      throw new HttpException (HTTP.STATUS_FORBIDDEN, in.getPath ());
  }

  public void processRequest (HttpOutputStream out) throws IOException {
    out.setHeader ("Content-type", HTTP.guessMimeType (file.getName ()));
    out.setHeader ("Content-length", String.valueOf (file.length ()));
    if (out.sendHeaders ()) {
      FileInputStream in = new FileInputStream (file);
      out.write (in);
      in.close ();
    }
  }
}


引用
但是就像我前面说的,有一个误差是无法避免的
就是服务器向客户端发送 最后一个字节 之后, 服务端就认为下载完毕,但是这最后一个字节是否传到了客户端 服务器无法知道,除非你再做个特殊的下载软件.


以上是JAVA实现的http server类,很显然,这种方式的误差,不是简单的在服务器发送完最后一个字节的误差,而是客户端在取消下载申请后,服务器断一样会认为客户端已经进行了下载,因为这种方式服务器端不知道客户端已经点击了取消下载按钮。

但是我认为服务器端应该是能够判断出客户端的下载情况的,不需要通过activex,因为那样的话太麻烦。
0 请登录后投票
   发表时间:2007-11-04  
fins同学好想忘记了一个问题,HTTP是无状态的。
服务器端发送一段数据(此处是文件)到浏览器,浏览器做相应的处理(此处是保存文件)在这个过程中浏览器只是被动的接受数据,如果在一段时间内没有接受到新的数据就会弹出无法下载的对话框(或者是不断的重试~~~~~)。在这一些行为中浏览器端始终是被动的,无状态的。这个问题从本质上是没有办法解决的。不过有一个非常不错的办法,上面的也有朋友提到了
可以在24小时内对一个账户重复下载一个资源进行一次扣费处理。
比如:
user1下载了一个资源rs1,按照常规的那样提示用户下载,然后扣费处理,如果下载成功也就完成任务了;如果下载失败用户可以重新下载rs1而不会被重复扣费,即使用户下载成功后也是可以重复下载的,(注意重复下载有一个有效时间比如24小时)这并不会造成什么损失(用户已经下载成功了,他重复下载等于说是重他硬盘上copy一份而已)。
0 请登录后投票
   发表时间:2007-11-04  
kjava 写道


引用
但是就像我前面说的,有一个误差是无法避免的
就是服务器向客户端发送 最后一个字节 之后, 服务端就认为下载完毕,但是这最后一个字节是否传到了客户端 服务器无法知道,除非你再做个特殊的下载软件.


以上是JAVA实现的http server类,很显然,这种方式的误差,不是简单的在服务器发送完最后一个字节的误差,而是客户端在取消下载申请后,服务器断一样会认为客户端已经进行了下载,因为这种方式服务器端不知道客户端已经点击了取消下载按钮。

但是我认为服务器端应该是能够判断出客户端的下载情况的,不需要通过activex,因为那样的话太麻烦。


一个完整的 httpFileserver 应该由自己来启动socket监听的
浏览器 通过socket连接到 httpFileserver , 浏览器断开后(取消下载,非法关闭等), 服务器是可以监听到的

你找的这个例子不能说明问题.


其实楼主举的这个例子 也能说明一些问题

你看那个 HttpOutputStream out

他实际上就是从 Socket.getOutputStream()的来的

如果这时候 客户端的 Socket断开时, out.write (in);  是会抛异常的
很明显的啊.
所以 服务端是可以知道 客户端是否已经下载完成的(除了我所说的那个误差).

请看下面的代码:
byte[] buff = new byte[2048];
while (true){
  int read = data.read( buff, 0, buff.length );
  if (read <= 0)
  break;
  out.write( buff, 0, read );
}
out.flush();
out.close();
// 此时 理解为 客户端成功下载完.

下载过程中,如果客户端中断,会抛出异常.你只要拦截处理一下就可以.

而如果顺利的执行完了 while循环,并且close了你就可以认为客户端下载完成了.
实际上,这时候一点误差都不会有, 因为你时在flush和close之后判断的.
如果你服务端不想主动flush 和 close,那么有可能存在2K的误差.
因为你最后一次执行out.write之后,有可能数据没有送到客户端.

只要稍微了解一下 HTTP SOCKET TCP/IP 的基础知识
你就应该能够理解我说的意思了 .

还有一点很重要:
我说的这个方案 是我自己亲自动手实践过的 绝对可行的.

最后再提醒一下楼主:
一个对下载 上传 要求严格的网站 ,必须要有一个很好的 http file server.
httpfile server 一个server级的东西,
而不是一个运行在某j2ee server下的servlet 或web listener.


0 请登录后投票
   发表时间:2007-11-04  
fireflyc 写道
fins同学好想忘记了一个问题,HTTP是无状态的。
服务器端发送一段数据(此处是文件)到浏览器,浏览器做相应的处理(此处是保存文件)在这个过程中浏览器只是被动的接受数据,如果在一段时间内没有接受到新的数据就会弹出无法下载的对话框(或者是不断的重试~~~~~)。在这一些行为中浏览器端始终是被动的,无状态的。这个问题从本质上是没有办法解决的。不过有一个非常不错的办法,上面的也有朋友提到了
可以在24小时内对一个账户重复下载一个资源进行一次扣费处理。
比如:
user1下载了一个资源rs1,按照常规的那样提示用户下载,然后扣费处理,如果下载成功也就完成任务了;如果下载失败用户可以重新下载rs1而不会被重复扣费,即使用户下载成功后也是可以重复下载的,(注意重复下载有一个有效时间比如24小时)这并不会造成什么损失(用户已经下载成功了,他重复下载等于说是重他硬盘上copy一份而已)。


楼主的问题核心是:
服务端 如何 判断 客户端 下载完成.

你说的"HTTP无状态  浏览器端始终是被动的,无状态的...." 和楼主的问题又什么关系吗???


你又说:
"然后扣费处理,如果下载成功也就完成任务了..."
楼主的问题就是, 你如何判断客户端"下载成功"????

0 请登录后投票
   发表时间:2007-11-05  
fins:
我觉得你使用socket直接进行编程和使用标准httpserver的结果是一样的。因为httpserver最终最底层也是使用socket实现的。退一步讲,使用socket能准确判知客户端浏览器是否下载成功,但是如果用户发现是误点链接造成的下载,他在浏览器提示保存时,取消了保存怎么办?因此还是不准确。只有在索取密码那种办法才能严格断定用户的行为:
1.他的确下载成功了,解压正常,但缺少密码。
2.他的确想使用该软件,如果是误点而实际并不想使用,他就不会索要密码了。要密码就证明了他想用。这儿密码的含义同购买软件serial number一样,具有确保软件真正是到达用户的作用。它间接的起到了证明用户成功获得软件的事实,证明了他主观上的确要想要下载该软件的,而不是误点造成的。
按照你们的做法,如果用户因为误点而被扣费,他们肯定会很生气,甚至会产生诉讼。
0 请登录后投票
   发表时间:2007-11-05  
rehte 写道
fins:
我觉得你使用socket直接进行编程和使用标准httpserver的结果是一样的。因为httpserver最终最底层也是使用socket实现的。

这点我当然清楚
但是显然楼主不清楚 ,所以我要解释给他听, 客户端断开连接 取消下载后, 服务端是可以知道的.

另外 ,我觉得你说这个和 楼主提的问题 没有什么关系
楼主的问题是
服务器端 如何 判断 客户端成功下载.

这里的问题 是 服务器端 与 客户端 ,是两台机器的事情.
如果非要把人的因素考虑进来 "他在浏览器提示保存时,取消了保存怎么办"
那我问你, 如果他保存了, 可是保存之后,才发现自己下载错了 ,又把文件删除了, 那服务端怎么知道?

楼主的问题是一个技术问题, 而楼上回答的 是一个 收费下载机制的实现方式问题.

我不知道楼主更需要的是哪个答案.

但是,我的观点是:
文件一旦下载到客户端, 那么就应该认为他下载成功了. 而他是否保存,是否删除,以及对他来说是否有用,我们无需关心 也无法正确判断.
毕竟互联网服务不是去超市买东西, 不包退不包换.

你打错电话了, 然后跟移动说, 我打错了, 刚才那电话的花费你别给我扣, 他们会答应吗????
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics