`
kjava
  • 浏览: 77355 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

 
阅读更多
这是一个技术难题。
需求是:
有一个收费的下载链接,但是是基于用户成功下载才能进行收费。

可是如何判断用户是否成功下载呢?

找了很多的技术文档,没有结果。其中常见的一种方案是:


  String file=request.getParameter("file");//物理文件路径
    String filename=file;
     if(file.startsWith("/"))
        file=session.getServletContext().getRealPath(file);
    if(file.indexOf("\\")>-1)
        filename=file.substring(filename.lastIndexOf("\\")+1);
    String err=null; String txt=null;
    System.out.println("filename: "+filename);
    byte data[]=null;
        try{
            InputStream inputStream = new FileInputStream(file); // 以byte流的方式打开文件 d:\1.gif
            int i=inputStream.available(); //得到文件大小
            data=new byte[i];
            inputStream.read(data); //读数据
            inputStream.close();
            inputStream=null;
        }catch(FileNotFoundException e){
            err="无法在服务器上获取相关文件!文件不存在.";
        }catch(Exception e){
            err=e.getMessage();
        }
     System.out.println(filename);
    if(data==null||err!=null){
        if(txt!=null)
           txt="请求的数据不是合法的二进制格式!";
        else{
            if(err==null)txt="无法从服务器获取相关文件,文件数据不存在或已经损坏.";
            else txt=err;
        }
        String msg="无法下载文件:"+filename+"\\n"+txt;
        return;
    }
    response.setContentType("application/octet-stream");
    response.addHeader("Content-disposition" , "attachment;filename="+filename+"\"");
    response.getOutputStream().write(data);
    response.getOutputStream().close();
    out.clear();
    out = pageContext.pushBody();
    data=null;                                                                 
    MD5 md=new MD5();
    String ip=request.getRemoteHost();
    System.out.println("下载成功!");
// 进行下载扣费


经过测试,发现这种方法不管客户端是否下载成功都会进行扣费,和


和下面的代码的执行效果是一样的

response.sendRedirect("dowloadfiel_url");
//进行扣费



但是我相信,WEB容器是肯定知道下载是否完成的,而且能够触发下载完成事件,否则,容器怎么知道什么时候停止向客户端发送数据流。


欢迎大家提供思路。

分享到:
评论
31 楼 realorg 2007-11-05  
我想如果我们是技术研讨的话,大家应该把问题放在“如何判断客户端已经下载成功”;
如果我们仅仅是为了解决“如何对已下载用户扣费”的问题,则 使用加密,再由扣费后给用户密码的方式应该是最合适的解决办法。

作为技术讨论,我想我们还是 来继续研究一下“如何判断客户端已经下载成功”。
等待高手ing....
30 楼 fins 2007-11-05  
rehte 写道
fins:
我觉得你使用socket直接进行编程和使用标准httpserver的结果是一样的。因为httpserver最终最底层也是使用socket实现的。

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

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

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

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

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

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

你打错电话了, 然后跟移动说, 我打错了, 刚才那电话的花费你别给我扣, 他们会答应吗????
29 楼 rehte 2007-11-05  
fins:
我觉得你使用socket直接进行编程和使用标准httpserver的结果是一样的。因为httpserver最终最底层也是使用socket实现的。退一步讲,使用socket能准确判知客户端浏览器是否下载成功,但是如果用户发现是误点链接造成的下载,他在浏览器提示保存时,取消了保存怎么办?因此还是不准确。只有在索取密码那种办法才能严格断定用户的行为:
1.他的确下载成功了,解压正常,但缺少密码。
2.他的确想使用该软件,如果是误点而实际并不想使用,他就不会索要密码了。要密码就证明了他想用。这儿密码的含义同购买软件serial number一样,具有确保软件真正是到达用户的作用。它间接的起到了证明用户成功获得软件的事实,证明了他主观上的确要想要下载该软件的,而不是误点造成的。
按照你们的做法,如果用户因为误点而被扣费,他们肯定会很生气,甚至会产生诉讼。
28 楼 fins 2007-11-04  
fireflyc 写道
fins同学好想忘记了一个问题,HTTP是无状态的。
服务器端发送一段数据(此处是文件)到浏览器,浏览器做相应的处理(此处是保存文件)在这个过程中浏览器只是被动的接受数据,如果在一段时间内没有接受到新的数据就会弹出无法下载的对话框(或者是不断的重试~~~~~)。在这一些行为中浏览器端始终是被动的,无状态的。这个问题从本质上是没有办法解决的。不过有一个非常不错的办法,上面的也有朋友提到了
可以在24小时内对一个账户重复下载一个资源进行一次扣费处理。
比如:
user1下载了一个资源rs1,按照常规的那样提示用户下载,然后扣费处理,如果下载成功也就完成任务了;如果下载失败用户可以重新下载rs1而不会被重复扣费,即使用户下载成功后也是可以重复下载的,(注意重复下载有一个有效时间比如24小时)这并不会造成什么损失(用户已经下载成功了,他重复下载等于说是重他硬盘上copy一份而已)。


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

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


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

27 楼 fins 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.


26 楼 fireflyc 2007-11-04  
fins同学好想忘记了一个问题,HTTP是无状态的。
服务器端发送一段数据(此处是文件)到浏览器,浏览器做相应的处理(此处是保存文件)在这个过程中浏览器只是被动的接受数据,如果在一段时间内没有接受到新的数据就会弹出无法下载的对话框(或者是不断的重试~~~~~)。在这一些行为中浏览器端始终是被动的,无状态的。这个问题从本质上是没有办法解决的。不过有一个非常不错的办法,上面的也有朋友提到了
可以在24小时内对一个账户重复下载一个资源进行一次扣费处理。
比如:
user1下载了一个资源rs1,按照常规的那样提示用户下载,然后扣费处理,如果下载成功也就完成任务了;如果下载失败用户可以重新下载rs1而不会被重复扣费,即使用户下载成功后也是可以重复下载的,(注意重复下载有一个有效时间比如24小时)这并不会造成什么损失(用户已经下载成功了,他重复下载等于说是重他硬盘上copy一份而已)。
25 楼 kjava 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,因为那样的话太麻烦。
24 楼 fins 2007-11-04  
这个问题 最好的解决方案就是自己写个简单的httpFile Server这个不难
网上有很多实现,简单的只要一个类就搞定

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

但是就像我前面说的,有一个误差是无法避免的
就是服务器向客户端发送 最后一个字节 之后, 服务端就认为下载完毕,但是这最后一个字节是否传到了客户端 服务器无法知道,除非你再做个特殊的下载软件.
23 楼 renavatior 2007-11-04  
这个可以用AJAX实现的吧,当下载完成它会触发一个事件这个时候提醒服务器端扣费
22 楼 rehte 2007-11-04  
我认为在不使用ActiveX等客户端下载软件的情况下,使用浏览器链接下载,可能只有上面那位老兄提的下载再索取密码扣费的方式是最准确的,甚至也只有那种办法才能确保用户真正的得到你的软件。
21 楼 kjava 2007-11-03  
引用
关键是“客户端下载是否完成”这个怎么理解?是不是当用户把文件完全保存到本地硬盘之后才算下载完成?


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

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

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

20 楼 onex 2007-11-02  
关注中
19 楼 someone 2007-11-02  
fins 写道
客户端 发送请求
服务端得到请求
服务端去读文件
服务端将读到的文件发送给客户端
服务端读取并发送完全部文件后,可以理解为客户端已经完成下载.
如果这期间客户端 中止下载, 那么服务端可以得到客户端的链接断开的信息

当然 这个思路是有误差的, 误差发生在最后时刻.
服务端"读取并发送完全部文件",但是客户端还没有接收到最后发送的那一部分内容时,会出现一点点误差,但是应该可以忽略不计的.


关键是“客户端下载是否完成”这个怎么理解?是不是当用户把文件完全保存到本地硬盘之后才算下载完成?

对于Web系统Download文件,是不可能在服务器端完全准确地判断文件是否Download成功了。浏览器都有buffer,对比较小的文件,当OutputStream().write已经结束,也就是数据已经完全发送到客户端,这个时候HttpConnect会关闭,一次Http会话结束,而这时客户端会弹出保存文件的对话框,当客户选择Cancel的时候,服务器端已经完全不知道了。

所以“跟踪 客户端下载是否完成”是无法实现的,除非你自己做ActiveX来下载。
18 楼 kjava 2007-11-02  
to fins

引用
客户端 发送请求
服务端得到请求
服务端去读文件
服务端将读到的文件发送给客户端
服务端读取并发送完全部文件后,可以理解为客户端已经完成下载.
如果这期间客户端 中止下载, 那么服务端可以得到客户端的链接断开
的信息

当然 这个思路是有误差的, 误差发生在最后时刻.
服务端"读取并发送完全部文件",但是客户端还没有接收到最后发送的那一部分内容时,会出现一点点误差,但是应该可以忽略不计的.


    response.setContentType("application/octet-stream");  
    response.addHeader("Content-disposition" , "attachment;filename="+filename+"\"");  
    while(发送文件大小完成)
    { 
    response.getOutputStream().write(data1);   
    response.getOutputStream().write(data2);

    .......
    }
    扣费操作.....
   
    
  
    response.getOutputStream().close();  



   以上的代码思路是不正确的,response.getOutputStream().write();写的数据其实还在服务器端,请求下载文件的触发请求 与 相应文件输出的下载流的操作 应该不是同一个线程,所以,以上的思路在下载过程中就会进行扣费。  


17 楼 myy 2007-11-01  
lszone 写道
myy 写道
服务端判断不太好做,也很不可靠。

建议这样:

将收费的东西打包压缩并加密码(最好能动态压缩),让别人随便下,但是没法直接用,然后用户必须点击页面的“扣费”按钮,进行扣费,才给出密码(也可以通过邮件发到用户邮箱中)


典型的不考虑产品的做法,对于一些方案总想绕道而行,你这种做法无疑是提高了操作的复杂性


很多共享软件就是这样做的,人家不是做产品么?

再说了,为什么要有麻烦的https,不就是因为http不安全绕道而行么?

“提高了操作的复杂性”是在有限条件下,需求要求过高 所必须付出的代价。
16 楼 lszone 2007-11-01  
myy 写道
服务端判断不太好做,也很不可靠。

建议这样:

将收费的东西打包压缩并加密码(最好能动态压缩),让别人随便下,但是没法直接用,然后用户必须点击页面的“扣费”按钮,进行扣费,才给出密码(也可以通过邮件发到用户邮箱中)


典型的不考虑产品的做法,对于一些方案总想绕道而行,你这种做法无疑是提高了操作的复杂性
15 楼 bearlz 2007-11-01  
    我以前在一家新闻图片销售公司做的时候,记录客户第一次下载的时间,生成订单,然后在一段时间内是免费下载的。
    控制客户端感觉比较难
14 楼 timerri 2007-11-01  
try{
response.getOutputStream().write(data);
response.getOutputStream().close();
}catch(e ...){
//失败
}

其实,这样就足够了,如果还是出问题,那就肯定是客户端的问题。

你们其实设计思路有问题,应该不是如何保证全部正确发送,这基本是做不到的,因为你不能保证客户端的正确与否,而是要保证客户在出现问题后还能有补救的办法,比如再让他能免费下一次。
13 楼 myy 2007-11-01  
to myy

引用
try{
InputStream inputStream = new FileInputStream(file); // 以byte流的方式打开文件 d:\1.gif
int i=inputStream.available(); //得到文件大小
data=new byte[i];
inputStream.read(data); //读数据

//
// 带密码压缩数据
//


不知道这段怎么理解?

to

inputStream.close();
inputStream=null;

}catch(FileNotFoundException e){
err="无法在服务器上获取相关文件!文件不存在.";
}catch(Exception e){
err=e.getMessage();
}



这不好理解么?

数据是服务端输出的,在输出前,压缩并加密了一下而已,比如简单一点可以这样:

1.用户 "user01" 请求文件"thedoc.doc"(如: http://.../getfile.jsp?file=thedoc.doc )
2.getfile.jsp先找到真正的thedoc.doc,并随机生成一个密码"asdfgh"(规则自定义)
3.getfile.jsp用命令行带参数(包括密码"asdfgh")调用rar.exe, 生成临时文件 user01_20071101100505_thedoc.doc.rar(规则自定义)
4.将文件名"user01_20071101100505_thedoc.doc.rar" 和 密码 "asdfgh"存入数据库
5.将文件 user01_20071101100505_thedoc.doc.rar 输出到用户

...

6.用户下载完成,用 winrar 打开(利用 winrar 验证文件是否完整),发现要密码才能解压,于是必须点“扣费”按钮(同时输入文件名"user01_20071101100505_thedoc.doc.rar"), 后台从数据库根据文件名,取出密码 "asdfgh"显示给用户。
12 楼 smyl9989 2007-10-31  
我怀疑你这个地方有没有try一下

response.getOutputStream().write(data);  
response.getOutputStream().close();

还有什么原因会导致客户端还没下完就出故障?突然停电?这是客户端的问题,这个难道还得你们负责啊

相关推荐

    阿里云OSS客户端Windows版本下载

    这款客户端简化了在Windows平台上与OSS交互的过程,使得用户无需编程或使用命令行工具就能完成文件操作。 描述中提到,“输入accessKeyId和accessKeySecret即可像FTP一样从本地上传文件到oss中”。这说明了使用OSS...

    svn客户端的下载

    4. 下载完成后,运行安装程序,按照向导指示进行安装。 安装完成后,你需要配置SVN客户端。在TortoiseSVN中,这通常涉及设置SVN服务器的URL,以及用户凭据(用户名和密码)。这些信息由你的项目管理员提供,或者...

    oss客户端macos版本

    - 断点续传:如果上传或下载过程中网络中断,客户端能记住进度并继续未完成的操作。 - 持续同步:可以设置客户端实时同步本地目录和OSS上的对应目录,保持数据一致性。 - 权限管理:用户可以设置不同级别的访问...

    最新版Git客户端下载

    ### 最新版Git客户端下载 #### 一、Git简介与重要性 Git 是一个分布式版本控制系统,用于跟踪在软件开发过程中对文件的修改。它最初由 Linus Torvalds 在 2005 年创建,旨在支持 Linux 内核的开发。Git 的核心功能...

    iphone手机办公客户端下载

    通过iPhone手机办公客户端,员工可以在外出差、家中或是任何有网络的地方,轻松完成工作任务,提高生产力。同时,企业也能通过这种方式实现远程办公,降低运营成本,提升组织的灵活性。 总之,"iPhone手机办公...

    小型FTP客户端支持续传和续下载

    3. **断点识别**:客户端需识别何时可以续传,例如,通过检查服务器的文件大小和本地已下载的部分来决定是否从头开始还是继续未完成的传输。 4. **错误处理和重试机制**:当网络问题导致传输中断时,客户端需要有...

    android客户端与服务端文件上传及下载

    4. 完成与通知:下载完成后,根据需求通知用户,如弹出通知或更新界面状态。 四、安全性与优化 1. 数据安全:在上传和下载过程中,确保数据传输的安全性,如使用HTTPS协议防止中间人攻击。 2. 断点续传:为了提高...

    大华DSS系列客户端操作手册.docx

    首先,用户需要下载并安装客户端程序,然后解压下载的客户端程序,双击并安装。安装完成后,用户需要单击“完成”以完成安装。 卸载 卸载DSS5000系列客户端需要按照一定的步骤进行。首先,用户需要选择“开始 &gt; ...

    TQ客户端.rarTQ客户端.rarTQ客户端.rarTQ客户端.rarTQ客户端.rarTQ客户端.rar

    7. 客户关系管理:对于销售团队,TQ客户端可能集成了CRM模块,便于管理客户资料,跟踪销售线索。 二、TQ客户端的技术特点: 1. 安全性:TQ客户端通常会采用加密技术保护用户数据安全,防止信息泄露。 2. 稳定性:...

    TortoiseSVN客户端下载

    该客户端是与Subversion(简称SVN)服务器紧密集成的,Subversion是一种开源的版本控制系统,用于跟踪文件和目录的更改,方便团队成员协作。 TortoiseSVN的最新版本为1.13.1.28686,提供了32位和64位两个版本,以...

    MFC 实现FTP客户端的上传下载(断点续传)

    8. **关闭连接**:完成所有操作后,客户端需要安全地关闭与FTP服务器的连接,释放资源。 在实现这些功能时,MFC提供了一系列的类和接口,如CInternetSession、CFTPConnection、CFTPFilePut和CFTPFileGet等,它们...

    SVN客户端 64位 包含中文包

    4. 安装完成后,SVN客户端将被添加到系统中,并且设置为中文界面。 5. 用户可以通过桌面快捷方式或开始菜单启动SVN客户端,开始进行版本控制操作。 SVN客户端的主要功能包括: 1. **版本库创建**:用户可以创建本地...

    svn客户端-windows版本

    SVN(Subversion)是一种广泛使用的版本控制系统,用于管理和跟踪文件和目录的变更。它允许团队成员协同工作,记录每次更改,以便于回滚错误,合并不同开发者的修改,并实现代码版本管理。在Windows环境下, SVN...

    GitHub for Mac 客户端

    **GitHub for Mac 客户端** GitHub for Mac 是一款专为苹果Mac OS X操作系统设计的图形用户界面(GUI)工具,它使得用户可以更轻松地与GitHub进行交互,包括克隆仓库、创建分支、提交更改、推送代码以及管理Pull ...

    plsqldeveloper11绿色(含oracle客户端).zip

    1. **代码编辑器**:提供了一个全面的代码编辑环境,支持PL/SQL语法高亮、自动完成、错误检查、调试等功能,帮助用户编写、修改和调试数据库脚本。 2. **对象浏览器**:允许用户浏览和管理Oracle数据库中的所有对象...

    未来教育NCRE考试客户端V1.0(包含客户端和机房管理软件)

    4. **即时反馈与评分**:完成练习或模拟考试后,系统立即给出分数和答案解析,便于考生及时了解自己的学习状况。 5. **时间管理训练**:模拟真实考试时间限制,培养考生在有限时间内高效答题的能力。 二、机房...

    SVN客户端64位(含汉化包)

    在下载了包含汉化包的SVN客户端64位压缩包后,首先解压文件,然后运行安装程序。在安装过程中,根据提示选择合适的安装路径,确保勾选“安装汉化包”选项,这样客户端将在安装完成后自动应用中文界面。 4. 使用...

    svn 客户端 64位

    2. **克隆版本库**:在本地电脑上,通过TortoiseSVN的" Checkout "功能,输入服务器的URL,选择存放项目的本地目录,完成下载。 3. **日常操作**:在本地工作副本上进行编辑、添加、删除等操作后,使用" Commit ...

    SQL2000客户端工具

    6. **SQL Profiler**:这是一个性能监视工具,用于跟踪SQL Server事件,如查询执行、索引使用和锁定问题。通过分析这些事件,用户可以识别性能瓶颈并优化数据库性能。 7. **数据库维护计划向导**:这个向导帮助用户...

Global site tag (gtag.js) - Google Analytics