zoukankan      html  css  js  c++  java
  • PHP服务器文件管理器开发小结(九):jQuery动态表单实现文件下载

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

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

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

    1
    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动态生成表单:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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接收该请求后,需要生成文件下载报文,将文件的内容填充到报文中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
                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以避免多余的文件输出。

    下面是具体效果:

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

  • 相关阅读:
    Linux学习篇(四):学习 gdb
    Linux学习篇(三):学习 gcc
    c#序列化感悟(重点讲讲二进制序列化)
    参数保存随笔
    写程序时try,catch查看报错的行号
    stram流char[]保存,支持中文,Filestram需要先转byte[]才能使用,但是性能更好《转载》
    c#序列化和反序列化《转载》
    如果两个测量设备出现相关性数据问题,且过度像素没区别?(打光效果一致),怎么办
    当Hobject类型出现内存泄漏爆炸增长的问题,怎么处理
    使用gige2500万相机时遇见的问题(条纹以及取图过久)
  • 原文地址:https://www.cnblogs.com/DoNetCShap/p/8789701.html
Copyright © 2011-2022 走看看