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

简单的文件下载可以通过将相对路径写入超链接的方式进行,然而这样仅限于服务端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以避免多余的文件输出。

下面是具体效果:

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

PHP服务器文件管理器开发小结(九):jQuery动态表单实现文件下载的更多相关文章

  1. python运维开发(十九)----Django后台表单验证、session、cookie、model操作

    内容目录: Django后台表单验证 CSRF加密传输 session.cookie model数据库操作 Django后台Form表单验证 Django中Form一般有2种功能: 1.用于做用户提交 ...

  2. jQuery formValidator表单验证插件

    什么是jQuery formValidator? jQuery formValidator表单验证插件是客户端表单验证插件. 在做B/S开发的时候,我们经常涉及到很多表单验证,例如新用户注册,填写个人 ...

  3. ASP.NET MVC Jquery Validate 表单验证的多种方式

    在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体验也会得到很大的提升.在开发过程中我们可以不借助 JS 库,自己去手写 JS ...

  4. jQuery Mobile 表单基础

    jQuery Mobile 会自动为 HTML 表单添加优异的便于触控的外观. jQuery Mobile 表单结构 jQuery Mobile 使用 CSS 来设置 HTML 表单元素的样式,以使其 ...

  5. [转]ASP.NET MVC Jquery Validate 表单验证的多种方式介绍

    在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体验也会得到很大的提升.在开发过程中我们可以不借助 JS 库,自己去手写 JS ...

  6. 通过AJAX和PHP,提交JQuery Mobile表单

    File name: callajax.php <?php $firstName = $_POST[firstName]; $lastName = $_POST[lastName]; echo( ...

  7. Jquery Validate 表单验证的多种方式

    ASP.NET MVC Jquery Validate 表单验证的多种方式 在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体 ...

  8. 雷林鹏分享:jQuery EasyUI 表单 - 创建异步提交表单

    jQuery EasyUI 表单 - 创建异步提交表单 本教程向您展示如何通过 easyui 提交一个表单(Form).我们创建一个带有 name.email 和 phone 字段的表单.通过使用 e ...

  9. 雷林鹏分享:jQuery EasyUI 表单 - 创建树形下拉框

    jQuery EasyUI 表单 - 创建树形下拉框 树形下拉框(ComboTree)是一个带有下列树形结构(Tree)的下拉框(ComboBox).它可以作为一个表单字段进行使用,可以提交给远程服务 ...

随机推荐

  1. web网页 页面布局的几种方式(转)

    web网页 页面布局的几种方式 转载 2017年06月16日 12:19:40 2218 网页基本布局方式: (1)流式布局 Fluid 流布局与固定宽度布局基本不同点 就在于对网站尺寸的侧量单位不同 ...

  2. unity3d MonoDevelop引用外部自定义dll文件报错:are you missing an assembly reference?

    在unity3d 编辑器 MonoDevelop 中引用外部自定义dll文件报错:are you missing an assembly reference? 因为unity还停留在.NET Fram ...

  3. 229B Planets

    传送门 题目大意 有编号1~n的星球,在不用的星球间共有m个传送门,任意两个星球间传送门不超过1个,每个传送门需要花费一定的时间,但是在某时刻会在某星球有旅客到达,这时要一定等到没有旅客到达的时候才能 ...

  4. CF 1027E Inverse Coloring

    当天晚上并没有看懂题意,然后就刚了40分钟F,但是没有弄出来呜呜呜. 推荐博客:  https://blog.csdn.net/Dream_maker_yk/article/details/81840 ...

  5. c++调用python引号的问题

    Boost.Python向python里面传递字符串时,引号是个很关键的问题. const char* cstr="hello \\\" world" // hello ...

  6. netty中的PoolChunk

    数据结构学的烂,看这个类比较的吃力 PoolChunk主要使用long allocate(int normCapacity) 在buffer pool中分配buffer.这个类有几个重要的概念:pag ...

  7. U盘刻录14.10镜像出问题的解决方法

    从几个月前的14.10 daily 版本就有U盘刻录无法启动的现象,相关bug可参见:https://bugs.launchpad.net/ubunt ... reator/+bug/1325801 ...

  8. Dojo Style Guide

    Contents: General Quick Reference Naming Conventions Specific Naming Conventions Files Variables Lay ...

  9. Python学习第三方库Requests: 让 HTTP 服务人类

    转自官方文档:http://cn.python-requests.org/zh_CN/latest/ 快速上手 http://cn.python-requests.org/zh_CN/latest/u ...

  10. django 学习之DRF (三)

    Django学习之DRF-03 视图集    1.视图集介绍    2.视图集基本使⽤        1.需求 使⽤视图集获取列表数据和单⼀数据        2.实现 class BookInfoV ...