常规实现方法:
ajax无法实现上传文件,因此常规情况下,要实现无刷新上传文件的做法,是在页面隐藏一个iframe,然后将上传form的target指向这个iframe,变相的实现。如下代码:
Uploading...
File:
upload_target是一个长宽都是0的iframe,所以页面上看不见他。还需要配合js,使得效果更好:
function startUpload(){
$('#uploading').show();
}
function finisheUpload(i){
$('#uploading').hide();
if(i==0)
{
alert("上传成功");
}
else
{
alert("上传失败");
}
}
其中startUpload方法是在提交表单的时候触发,而由于没有什么回调函数,因此finisheUpload只能由upload.php文件的输出控制。通常就是在输出中输出一段javascript代码来执行。
php代码如下:
header("Content-Type:text/html;charset=utf-8");
$destination_path = getcwd().DIRECTORY_SEPARATOR;
$filname = $destination_path . basename( $_FILES['myfile']['name']);
$filname=iconv("UTF-8","gb2312",$filname);
if(move_uploaded_file($_FILES['myfile']['tmp_name'], $filname)) {
echo " ";
}
else
{
echo " ";
}
注意,输出javascript的时候,由于调用的js方法是在iframe外定义的,要在iframe内调用js方法,需要指定window.parent。
————————
HTML5下的实现方法:
先介绍一下FileReader对象:
FileReader对象的详细说明可以在W3C官方文档中查看。
该接口提供方法来读取文件对象或者Blob对象。它继承了EventTarget,接口的描述如下:
[Constructor]
interface FileReader: EventTarget {
// async read methods
void readAsArrayBuffer(Blob blob);
void readAsText(Blob blob, optional DOMString label);
void readAsDataURL(Blob blob);
void abort();
// states
const unsigned short EMPTY = 0;
const unsigned short LOADING = 1;
const unsigned short DONE = 2;
readonly attribute unsigned short readyState;
// File or Blob data
readonly attribute (DOMString or ArrayBuffer)? result;
readonly attribute DOMError? error;
// event handler attributes
attribute EventHandler attribute EventHandler onprogress;
attribute EventHandler attribute EventHandler onabort;
attribute EventHandler onerror;
attribute EventHandler };
可以看到有4个异步方法,其中3个是读取,1个是放弃,4个状态属性,1个result,1个error和6个事件。(之前还有readAsBinaryString方法,不过已经被W3C去除了)这6个事件的触发时机如下:
loadstart --When the read starts.
progress --While reading (and decoding) blob
abort --When the read has been aborted. For instance, by invoking the abort() method.
error --When the read has failed (see errors).
load --When the read has successfully completed.
loadend --When the request has completed (either in success or failure).
下面演示一个例子,读取一个文本文档,并且alert出来内容。
function readfile(dom)
{
var file = dom.files[0];
var textType = /text.*/;//正则表达式,使之匹配text/html,text/plain
if (file.type.match(textType)) {
var reader = new FileReader();
//注册事件函数,即等读完内容后,要做的事情
reader.onload = function(e) {
alert(reader.result);
}
//异步读取内容
reader.readAsText(file,'gb2312');
$("#msg").html("正在执行异步读取");
}
else {
alert("文件不支持");
}
}
——————————————————————————————
下面演示一个例子,读取一个DataURL的,DataURL其实是一种DataURI(要知道URI的更多细节,可以去http://css-tricks.com/data-uris/,或者维基百科了解更多)。它提供了一种在浏览器中显示数据的途径。比如你要显示一个图片(百度的logo)的话,你可以如下写:
你也可以用它的URI去写,如下:
src中填写的字符串就是DataURI,格式如下:
data:[][;charset=][;base64],
这种URI其实很有用的,可以减少HTTP请求,使得网站提速。因此获取了URI的话就可以加载本地的图像了。示例代码如下:
function loadimg(dom)
{
var file = dom.files[0];
//正则表达式,使之匹配p_w_picpath/jpeg等
var p_w_picpathType = /p_w_picpath.*/;
if (file.type.match(p_w_picpathType)) {
var reader = new FileReader();
reader.onload = function(e) {
var img = new Image();
img.src = reader.result;
$("#divimg").append(img);
}
reader.readAsDataURL(file);
}
else {
alert("文件不支持");
}
}
————————————————————————————————————
还有一个方法是readAsArrayBuffer,从字面就可以看出,是把文件读取到一个数组缓冲区。
使用readAsArrayBuffer这种方法实现上传文件
下面演示一个例子:
function upload()
{
var file = $('#testfiles')[0].files[0];
var reader = new FileReader();
reader.onload = function (rResult) {
var filename = file.name;
var options = {
type: 'POST',
url: 'upload.php?filename='+filename,
data: reader.result,
success:function(result){
alert(result.msg);
},
processData: false, // 告诉jQuery不要去处理发送的数据
contentType: false, // 告诉jQuery不要去设置Content-Type请求头
dataType:"json"
};
$.ajax(options);
};
reader.readAsArrayBuffer(file);
}
后端PHP代码:
try{
$filename=$_GET['filename'];
$input = file_get_contents("php://input"); //这个是获取请求的InputStream,PHP下的写法
file_put_contents($filename, $input);//保存成文件。
echo json_encode(array("msg"=>"上传成功"));
}
catch(Exception $e)
{
echo json_encode(array("msg"=>"上传失败"));
}
FormData方法
FromData的官方说明在这里。利用FormData对象,你可以使用一系列的键值对来模拟一个完整的表单。
以下给出一个例子,允许上传多个文件:
function upload()
{
var formdata = new FormData();
$.each($('#testfiles')[0].files, function(i, file) {
formdata.append('file-'+i, file);
});
var options = {
type: 'POST',
url: 'upload.php',
data: formdata,
success:function(result){
alert(result.msg);
},
processData: false, // 告诉jQuery不要去处理发送的数据
contentType: false, // 告诉jQuery不要去设置Content-Type请求头
dataType:"json"
};
$.ajax(options);
}
后台PHP代码:
try
{
foreach($_FILES as $key => $value)
{
//print_r ($_FILES[$key]); echo "
";
move_uploaded_file( $value["tmp_name"], $value['name']);
}
echo json_encode(array("msg"=>"上传成功"));
}
catch(Exception $e)
{
echo json_encode(array("msg"=>"上传失败"));
}
参考文档: