该帖已经被评为隐藏帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-11-03
引用 关键是“客户端下载是否完成”这个怎么理解?是不是当用户把文件完全保存到本地硬盘之后才算下载完成?
不错,客户端下载完成的含义就是用户把文件保存到本地硬盘。 之所以进行这样的定义,是为了更准确地判断出,该点击用户确实是想下载该文件的用户,而不是被误导或是其他不正常原因而导致点击了下载链接。因为后面紧跟着扣费操作! 如果用户仅仅是点击了下载连接,而取消了下载确认对话框,那么显然,这个用户对该文件不感兴趣,扣费操作是不应该执行的。 而且,我想知道的是,如果不能准确判断用户是否下载了文件,为什么要用一大堆的代码去 读文件,发文件,而不是用一条 response.sendForward(url),效果不是一样的吗? |
|
返回顶楼 | |
发表时间:2007-11-04
我认为在不使用ActiveX等客户端下载软件的情况下,使用浏览器链接下载,可能只有上面那位老兄提的下载再索取密码扣费的方式是最准确的,甚至也只有那种办法才能确保用户真正的得到你的软件。
|
|
返回顶楼 | |
发表时间:2007-11-04
这个可以用AJAX实现的吧,当下载完成它会触发一个事件这个时候提醒服务器端扣费
|
|
返回顶楼 | |
发表时间:2007-11-04
这个问题 最好的解决方案就是自己写个简单的httpFile Server这个不难
网上有很多实现,简单的只要一个类就搞定 这样你就可以处理很多事情了 但是就像我前面说的,有一个误差是无法避免的 就是服务器向客户端发送 最后一个字节 之后, 服务端就认为下载完毕,但是这最后一个字节是否传到了客户端 服务器无法知道,除非你再做个特殊的下载软件. |
|
返回顶楼 | |
发表时间: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,因为那样的话太麻烦。 |
|
返回顶楼 | |
发表时间:2007-11-04
fins同学好想忘记了一个问题,HTTP是无状态的。
服务器端发送一段数据(此处是文件)到浏览器,浏览器做相应的处理(此处是保存文件)在这个过程中浏览器只是被动的接受数据,如果在一段时间内没有接受到新的数据就会弹出无法下载的对话框(或者是不断的重试~~~~~)。在这一些行为中浏览器端始终是被动的,无状态的。这个问题从本质上是没有办法解决的。不过有一个非常不错的办法,上面的也有朋友提到了 可以在24小时内对一个账户重复下载一个资源进行一次扣费处理。 比如: user1下载了一个资源rs1,按照常规的那样提示用户下载,然后扣费处理,如果下载成功也就完成任务了;如果下载失败用户可以重新下载rs1而不会被重复扣费,即使用户下载成功后也是可以重复下载的,(注意重复下载有一个有效时间比如24小时)这并不会造成什么损失(用户已经下载成功了,他重复下载等于说是重他硬盘上copy一份而已)。 |
|
返回顶楼 | |
发表时间: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. |
|
返回顶楼 | |
发表时间:2007-11-04
fireflyc 写道 fins同学好想忘记了一个问题,HTTP是无状态的。
服务器端发送一段数据(此处是文件)到浏览器,浏览器做相应的处理(此处是保存文件)在这个过程中浏览器只是被动的接受数据,如果在一段时间内没有接受到新的数据就会弹出无法下载的对话框(或者是不断的重试~~~~~)。在这一些行为中浏览器端始终是被动的,无状态的。这个问题从本质上是没有办法解决的。不过有一个非常不错的办法,上面的也有朋友提到了 可以在24小时内对一个账户重复下载一个资源进行一次扣费处理。 比如: user1下载了一个资源rs1,按照常规的那样提示用户下载,然后扣费处理,如果下载成功也就完成任务了;如果下载失败用户可以重新下载rs1而不会被重复扣费,即使用户下载成功后也是可以重复下载的,(注意重复下载有一个有效时间比如24小时)这并不会造成什么损失(用户已经下载成功了,他重复下载等于说是重他硬盘上copy一份而已)。 楼主的问题核心是: 服务端 如何 判断 客户端 下载完成. 你说的"HTTP无状态 浏览器端始终是被动的,无状态的...." 和楼主的问题又什么关系吗??? 你又说: "然后扣费处理,如果下载成功也就完成任务了..." 楼主的问题就是, 你如何判断客户端"下载成功"???? |
|
返回顶楼 | |
发表时间:2007-11-05
fins:
我觉得你使用socket直接进行编程和使用标准httpserver的结果是一样的。因为httpserver最终最底层也是使用socket实现的。退一步讲,使用socket能准确判知客户端浏览器是否下载成功,但是如果用户发现是误点链接造成的下载,他在浏览器提示保存时,取消了保存怎么办?因此还是不准确。只有在索取密码那种办法才能严格断定用户的行为: 1.他的确下载成功了,解压正常,但缺少密码。 2.他的确想使用该软件,如果是误点而实际并不想使用,他就不会索要密码了。要密码就证明了他想用。这儿密码的含义同购买软件serial number一样,具有确保软件真正是到达用户的作用。它间接的起到了证明用户成功获得软件的事实,证明了他主观上的确要想要下载该软件的,而不是误点造成的。 按照你们的做法,如果用户因为误点而被扣费,他们肯定会很生气,甚至会产生诉讼。 |
|
返回顶楼 | |
发表时间:2007-11-05
rehte 写道 fins:
我觉得你使用socket直接进行编程和使用标准httpserver的结果是一样的。因为httpserver最终最底层也是使用socket实现的。 这点我当然清楚 但是显然楼主不清楚 ,所以我要解释给他听, 客户端断开连接 取消下载后, 服务端是可以知道的. 另外 ,我觉得你说这个和 楼主提的问题 没有什么关系 楼主的问题是 服务器端 如何 判断 客户端成功下载. 这里的问题 是 服务器端 与 客户端 ,是两台机器的事情. 如果非要把人的因素考虑进来 "他在浏览器提示保存时,取消了保存怎么办" 那我问你, 如果他保存了, 可是保存之后,才发现自己下载错了 ,又把文件删除了, 那服务端怎么知道? 楼主的问题是一个技术问题, 而楼上回答的 是一个 收费下载机制的实现方式问题. 我不知道楼主更需要的是哪个答案. 但是,我的观点是: 文件一旦下载到客户端, 那么就应该认为他下载成功了. 而他是否保存,是否删除,以及对他来说是否有用,我们无需关心 也无法正确判断. 毕竟互联网服务不是去超市买东西, 不包退不包换. 你打错电话了, 然后跟移动说, 我打错了, 刚才那电话的花费你别给我扣, 他们会答应吗???? |
|
返回顶楼 | |