前文讨论的文件操作,无论是新建、编辑、移动、删除,都是服务端对本地文件系统的操作。这一节需要讨论一个涉及服务端和客户端协调进行的操作:文件下载。

简单的文件下载可以通过将相对路径写入超链接的方式进行,然而这样仅限于服务端Apache有下载权限的文档,如果需要支持对更多文件进行下载,仅仅使用这一方式就远远不够了。这里需要利用PHP的能力,在服务端“取出”文件并“推送”给客户端。

首先是生成下载图标链接:

 if           (          is_readable          (          $filePath          ))           $info          .=           "<li><a href=\"#\" title=\"download\" onClick=\"onDownload('$filePath')\"><img src=\"images/download32.png\" alt=\"\" class=\"tabmenu\"/></a></li>"          ;

这里之所以使用onDownload而不是前文的onElemAct,是为了强调此处不需要jQueryUI的前端提示。当远程文件被推送到本地后,会直接在浏览器中形成下载提示。

由于要利用浏览器默认的文件下载行为,因此需要使用表单而不是jQuery的Ajax系统,因为不用处理返回数据。然而,这个表单应该是对客户隐形的,因此考虑用jQuery动态生成表单:

function           onDownload(strFilePath)         
          {         
                    var           formDownload=$(          "<form>"          );         
                    formDownload.attr(          "id"          ,           "frmDownload"          );         
                    formDownload.attr(          "style"          ,          "display:none"          );         
                    formDownload.attr(          "target"          ,          "_self"          );         
                    formDownload.attr(          "method"          ,          "post"          );         
                    formDownload.attr(          "action"          ,          "query.php"          );         
                    var           inputDownloadAct=$(          "<input>"          );         
                    inputDownloadAct.attr(          "type"          ,          "hidden"          );         
                    inputDownloadAct.attr(          "name"          ,          "act"          );         
                    inputDownloadAct.attr(          "value"          ,           "download"          );         
                    var           inputDownloadFile=$(          "<input>"          );         
                    inputDownloadFile.attr(          "type"          ,          "hidden"          );         
                    inputDownloadFile.attr(          "name"          ,          "file"          );         
                    inputDownloadFile.attr(          "value"          , strFilePath);         
                    $(          "body"          ).append(formDownload);         
                    formDownload.append(inputDownloadAct);         
                    formDownload.append(inputDownloadFile);         
                    formDownload.submit();          
                    formDownload.remove();         
          }

这里将表单的target指向_self,这样就不会弹出额外的窗口。利用append将表单填充到页面body的尾部,用submit提交表单后,再用remove删除表单。注意这里使用的post请求,对应的act是download,name是文件路径。

PHP接收该请求后,需要生成文件下载报文,将文件的内容填充到报文中。

case           "download"          :         
                    $isDirContentView           = false;         
                    if           (isset(          $_POST          [          "file"          ]))         
                    {         
                    $filePath           = urldecode(          $_POST          [          "file"          ]);         
                    header(          "Content-Type: application/octet-stream"          );         
                    header(          "content-disposition: attachment;filename="          .          basename          (          $filePath          ));         
                    header(          "content-length:"          .          filesize          (          $filePath          ));         
                    readfile(          $filePath          );         
                    }         
                    break          ;

这里,使用header函数添加额外的报头,使得报文符合合适的下载报文格式。其中重要的是为Content-Type指定合适的值,才能使浏览器正确分析该报文。具体值的选择可以参考对照表。

将文件长度写到content-length中,然后使用readfile将文件内容读取到响应报文中。同时,将$isDirConentView置为false以避免多余的文件输出。

下面是具体效果:

jquery 下载zip文件流_文件下载

值得注意的是,如果使用迅雷之类下载工具捕获这一下载请求的话,其会将POST请求该为GET请求,并使得请求内容不可控。因此本节提供的方法仅适用于使用浏览器直接下载的情况。