uncategorized

html5 FormData提交大文件

昨天, 向服务器抛送一个大文件用的是Real Ajax Uploader这个插件, 不过老大觉的
这个插件的太复杂了, 要我自己写个简单能实现单个文件大文件的上传功能就可以了,自己
找了一点资料看看, 实现的原理就是把一个很大的文件分割, 每次向服务器抛送一部分, 那
么我们自己就要用js构建表单向服务器发送数据, 发现html5的这个FormData可以让我们自
己构建一个新的表单发送给服务器.

关于FormData的介绍, 可以参考这个帮助文档
FormData : Object
使用FormData对象

下面就写一个可以上传的简单例子, 第一个是js文件
upload.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//检查是否已经选择了文件, fileId是文件input输入框的id
function checkFile(fileId) {
var files = document.getElementById(fileId).files;

if (files.length <= 0) {
return false;
}

return files;
}

//返回指定范围的blob对象
function readBlob(file, startByte, stopByte) {
var start = parseInt(startByte) || 0;
var stop = parseInt(stopByte) || file.size;

return file.slice(start, stop);
}

//向服务器上传数据, 依赖jquery的支持
function upload(file, argument, successCallback, progressCallback, failCallback) {
var formData = new FormData();
var stopByte = argument.CurPos + argument.UploadLimit;
var content = readBlob(file, argument.CurPos, stopByte < argument.FileSize ? stopByte : argument.FileSize);
formData.append("FileName", argument.FileName);
formData.append("FileSize", argument.FileSize);
formData.append("FirstRequest", argument.FirstRequest);
formData.append("Content", content);
$.ajax({
url: argument.Url,
method: "POST",
data: formData,
processData: false,
contentType: false,
success: function(responseData) {
var json = JSON.parse(responseData);
//查看状态码, 200表示发送已经完成, 206表示部分上传
if (json.statusCode === 200) {
if (successCallback) {
successCallback(json);
}
}
else if (json.statusCode === 206) {
if (progressCallback) {
progressCallback(argument.CurPos, argument.FileSize);
}
argument.FirstRequest = "false";
argument.CurPos = argument.CurPos + argument.UploadLimit;
upload(file, argument, successCallback, progressCallback, failCallback);
}
else {
if (failCallback) {
failCallback(responseData);
}
}
},
error: function(responseData) {
if (failCallback) {
failCallback(responseData);
}
}
});
}

//上传对外的接口
function uploadLargeFile(url, fileId, successCallback, progressCallback, failCallback) {
var files = checkFile(fileId);
if (!files) {
return;
}

var argument = {
"FileName" : files[0].name,
"FileSize" : files[0].size,
"FirstRequest" : "true",
"Url": url,
"CurPos": 0,
"UploadLimit": 1 * 1024 * 1024,
}

upload(files[0], argument, successCallback, progressCallback, failCallback);
}

以上是上传文件的js文件, 下面是配置此js的前端
index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/upload.js"></script>
</head>
<body>
<input type="file" id="upload_file">
<input type="button" id="click" value="上传大文件">
<div id="displayProgress"></div>
</body>

<script>
$("#click").click(function() {
var displayProgress = $("#displayProgress");
uploadLargeFile("upload.php", "upload_file", function (responseData) {
displayProgress.html("文件上传成功! 远程地址是: " + responseData.remotePath);
var obj = document.getElementbyId("upload_file");
//清楚所选择的文件
obj.outerHTML = obj.outerHTML;
}, function (curPos, fileSize) {
var progress = Math.round(100 * curPos / fileSize);
displayProgress.html(progress + "%");
}, function (responseData) {
displayProgress(responseData);
}
);
});
</script>

</html>

有了上面的前端的东西, 下面是后台的php文件的配合了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php

function makeDir($dir) {
if (!file_exists($dir) && !empty($dir)) {
$done = @mkdir($dir, 0777, true);

if (!$done) {
$ret = array("statusCode" => "800", "message" => "Cannot create upload folder");
die(json_encode($ret));
}
}
}

$uploadPath = "upload/largeFile/";
$filePath = $uploadPath . $_REQUEST["FileName"];
$dir = dirname($filePath);
makeDir($dir);

if ($_REQUEST["FirsiRequest"] === "true") {
if (file_exists($filePath)) {
@unlink($filePath);
}
}

//formData post files just normal upload in $_FILES, older ajax upload post it in input
$post_bytes = file_get_contents( isset($_FILES['Content']) ? $_FILES['Content']['tmp_name'] : 'php://input' );

file_put_contents($filePath, $post_bytes, FILE_APPEND);

$curFileSize = filesize($filePath);

if ($curFileSize >= $_REQUEST["FileSize"]) {
$ret = array("statusCode" => 200, "remotePath"=> $filePath);
}
else if ($curFileSize < $_REQUEST["FileSize"]) {
$ret = array("statusCode" => 206);
}

echo json_encode($ret);

hexo配合七牛的插件还没弄好, 暂时就不传演示的图片了.大家可以自己下载代码看看行不
行, 我用的是nginx服务器, 本地测试过1G的大文件.

参考

HTML5 FormData 进行文件jquery ajax 上传 到又拍云

相关文章

HTML5新特性之文件和二进制数据的操作