WEB上传文件

WEB上传文件

html

<form enctype='multipart/form-data' methed='POST'>
    <input type='file' name='_file'>
</form>

这里需要注意的有三点:
1. <input>标签的type值需设定为file。
2. 提交方法设定为POST。
3. enctype属性规定在发送到服务器之前应该如何对表单数据进行编码。默认地,表单数据会编码为 “application/x-www-form-urlencoded”。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 “+” 加号,特殊符号转换为 ASCII HEX 值)。

概述
application/x-www-form-urlencoded在发送前编码所有字符(默认)
multipart/form-data不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain空格转换为 “+” 加号,但不对特殊字符编码

js

<input>中的text,select,checkbox,radio和textaea类型的数据的提交十分相似。将他们整合在一个form表单中,结合JQuery的$.ajax,可以使用.serialize()方法很方便的将所有信息一并传输给服务器端。
但是,.serialize()方法不处理type为file的输入。所以我们不得不寻找另一条路:FormData。利用FormData对象,我们可以通过 JavaScript 用一些键值对来模拟一系列表单控件,我们还可以使用 XMLHttpRequest 的·send()方法来异步的提交表单。与普通的 Ajax 相比,使用 FormData 的最大优点就是我们可以异步上传二进制文件。

创建FormData对象

创建一个空的FomData对象,然后用append()方法向对象内添加字

var oMyForm = new FormData();

oMyForm.append("username", "Groucho");
oMyForm.append("accountnum", 123456); // 数字123456被立即转换成字符串"123456"

// fileInputElement中已经包含了用户所选择的文件
oMyForm.append("userfile", fileInputElement.files[0]);

var oFileBody = "<a id="a"><b id="b">hey!</b></a>"; // Blob对象包含的文件内容
var oBlob = new Blob([oFileBody], { type: "text/xml"});

oMyForm.append("webmasterfile", oBlob);

var oReq = new XMLHttpRequest();
oReq.open("POST", "http://foo.com/submitform.php");
oReq.send(oMyForm);
使用html表单来初始化FormData对象

使用已有的form表单DOM对象作为FormData的初始化参数,即可构造出包含改表单所有输入信息的FormData对象。

var formElement = document.getElementById("myFormElement");
form_data = new FormData(formElement);

//使用XMLHttpRequest 的 send() 方法来异步的提交表单
var oReq = new XMLHttpRequest();
oReq.open("POST", "submitform.php");
oReq.send(new FormData(formElement));

//使用JQuery的$,ajax
var fd = new FormData(document.getElementById("fileinfo"));
fd.append("CustomField", "This is some extra data");
$.ajax({
  url: "stash.php",
  type: "POST",
  data: fd,
  processData: false,  // 告诉jQuery不要去处理发送的数据
  contentType: false   // 告诉jQuery不要去设置Content-Type请求头
});

tips:
1. 此处为DOM对象而非JQuery对象
2. 初始化后的FormData对象中包含文件输入,故问题解决。

提交对象

使用XMLHttpRequest 的 send() 方法来异步的提交表单

var oReq = new XMLHttpRequest();
oReq.open("POST", "submitform.php");
oReq.send(form_data);

使用JQuery的$,ajax

$.ajax({
  url: "stash.php",
  type: "POST",
  data: form_data,
  processData: false,  // 告诉jQuery不要去处理发送的数据
  contentType: false   // 告诉jQuery不要去设置Content-Type请求头
});

php

php作为后台的服务程序,所要做的就是将前台上传的文件检查并接收。此时使用传统的$_POST超级全局变量是无法获取文件信息和内容的。那么我们不禁要问,文件去哪了呢?
原来,原文件通过二进制数据流传输到了后台服务器,服务器只是将其作为一个临时文件.tmp存储了起来。我们可以通过$_FILES来获取文件的信息:

超级全局变量描述
$_FILE[‘userfile’][‘name’]客户端机器文件的原名称
$_FILE[‘userfile’][‘type’]文件的MIME类型
$_FILE[‘userfile’][‘size’]已上传的文件大小
$_FILE[‘userfile’][‘tmpname’]文件被上传后在服务器存储的临时文件名
$_FILE[‘userfile’][‘error’]和该文件上传的错误代码

我们可以利用这些信息来检查文件的大小、类型等等。如果我们希望保存这个文件则可以将该临时文件转移至另一个位置:

    move_uploaded_file($_FILE['userfile']['tmpname'], $file_name);

其中$file_name是目标文件位置。这样一来,该文件就成为了网站资源的一部分,可供我们随时调用。

篇外

在最开始,我思考的方法是将上传的文件存储在数据库中,是弯路亦或是正途为现在还不知道。
mysql中有blob类型的字段可以储存二进制数据流,按照这个思路,工作的流程便是读取文件流—->INSERT INTO 数据库。
在php中可以使用fopen() fread()来读取文件

        //读取临时文件
        $fp = fopen($tmp_name, 'r');
        $content = fread($p, $size);
        fclose($fp);

        //在每个双引号添加反斜杠
        $content = addslashes($content);

        //插入MySQL数据库(与普通类型的操作方式一样)
        $sql = "INSERT INTO leavenote (id, username, file) VALUES ('{$id}', '{$username}','{$content}')";
        $mysqli -> query($sql);

使用该方法遇到的困难是:

  1. 文件以二进制数据流的形式存放,读取该文件必须先将其转换为原来的类型
  2. 文件类型为.bin,并不携带原文件信息,还需为其设立额外的字段来纪录这些信息、

相比较之下,我选择在数据库中存储文件的位置信息,将文件本身独立存放,使用时通过数据库中的文件位置信息来查找。
在下作为一个小白,仍处于摸索阶段,若有博友有好的建议和想法,欢迎指正。


使用FormData对象
MDN—FormData
参考Blog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值