今天遇到一个问题,关于大文件的上传。其实不管是大文件的上传,还是普通的文件上传,一直都是迷迷糊糊的,今天对其进行整理下。
首先,最基本的,文件大小单位
1KB等于1024B,B是英文Byte(比特,字节)的缩写,KB即kilobyte,字面意思就是千比特。
byte是文件大小的一个计量单位,大家都知道在计算机里面,文件都是以二进制方式存储的,这样一个最小的存储单元(譬如10、11、01、00)叫做一个bit(位,位元),八个位元等于一个比特。
转换关系:
8bit=1b
1024byte=1kb
1024kb=1mb
1024mb=1gb
1024gb=1tb
以上单位k指千、m指百万、g指10亿,t指万亿,大小写均可。
因为1024≈1000,所以1024b,也称为1k,以下类似。
简单点说就是 1G =1024M 1M = 1024K 1K=1024B B之后就是位了,8位是1B,一般都是B为计量单位。
html :1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form action="upload_file.php" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
这个是以最基本的表单提交方式,当点击提交的时候文件就直接飞到upload_file.php那边了,注意接受的变量以表单控件的name字段的内容为变量名($_POST[])数组里面(想了下,其实框架的路由都是从这些大数组里面获取变量的信息)。
这个 enctype 很重要
标签的 type=”file” 属性规定了应该把输入作为文件来处理。举例来说,当在浏览器中预览时,会看到输入框旁边有一个浏览按钮。
不仅是这块,当用curl模拟文件上传的时候,也有相关的参数设置1
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
这个param如果是普通的post数据提交,要拼接成&这种string方式,如果是文件上传,直接是传输组参数就可以了。
php
1 | <?php |
之前一直以为这是框架的内容,其实这是php自带的,框架可能只是对他的封装和安全性的校验。如果有时候实在上传出错,试试这个数组。
几个要注意的点:
- 临时上传文件的地址可以通过phpinfo() 查看,但如果你真到那个文件夹下是找不到的,通过move_uploaded_file 函数移动到你需要的位置。因为我们itbasic之前的上传都写好了,导致我以为上传直接上传到指定的文件夹。
- 几个函数 is_dir 判断文件夹是否存在,file_exists,判断文件是否存在,
move_uploaded_file 移动文件。注意创建文件夹的时候给权限755. - 移动到新的地址直接返回新的地址给前端就可以了。
- 注意一下我们平时比如itbasic上表单的提交都不是以form这种格式,都是直接通过按钮触发click事件,然后获取页面内容进行提交,这种方式是上传不了文件的,我们可以利用jq,
1
2var writeData = new FormData();
writeData.append('object', objid);
然后往里面添加属性,通过append
- 之前还上传过base64格式的image图片,其实这个要比前面的文件上传简单很多,这个与其说是上传文件,不如说是保存数据内容。
一个image的base64格式码:1
data:image/png;base64,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
图片在使用的时候只用image src=”” 等于上面这串内容就可以了。像wangeditor里面,写的内容,两种保存图片的方式:1.base64, 直接把这个image src = base64格式保存在html中 2.把文件上传到服务器上,然后获取链接地址。
base64 php处理代码:1
2
3
4
5
6
7
8
9
10if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $src, $result)){
$type = $result[2];
$body = str_replace($result[1], '', $src);
$filename = $path.date('YmdHis', time()).'.'.$type;
if (file_put_contents($filename, base64_decode($body))){
}else{
return ['code'=>CODE_ERROR, 'msg'=>'文件保存失败'];
}
}
大致说下一下,type 获取的是正则 (\w+)里面内容,代表图片的格式,
body 获取的正则的内容,注意看表达式最外面的()括号,result[0]代表的是完全匹配内容。
php获取到图片base64加密后的内容,通过解密,file_put_contents 写入文件,返回文件地址。
上面是通过前端 js + 后端php,实现的文件上传,其实完全可以通过 php + php 实现,下面分别介绍通过这两种方式实现的大文件上传。
客户端php代码
1 | #!/usr/bin/env php |
http_post_data 是通过curl封装的post方法,需要注意的点是,传的post参数不要组装成string(post三种传递数据方式,string, 表单还有一种),其实我们平时可以通过观察控制台,发现我们itbasic的每次提交都是post方式,但是数据组装方式,有string,表单两种类型。
还有注意我之前一直file以为传文件名就可以了,··坑爹啊··这样传服务端怎么获取内容,用file_get_contents()获取文件内容。
(今天偶然碰见,file_get_contents()不能获取itbasic.app这种本地定义的域名哦)。
- php读取指定文件大小
- 完整的php接受大文件上传
上传大文件 js1
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167var uploadToDatrix = function(fileObject, fileId, fileText, type, dirid, dirobj, pro, button) { //参数是上传文件对象
if (button) {
$('#' + button).attr('disabled', 'disabled');
}
for (var i = 0; i<fileObject.files.length; i++) {
var file = fileObject.files[i]; //具体的文件
var filename = file.name;
var fileSize = file.size; console.log(file);
var data = {
filename: filename,
filesize: fileSize,
createuid: DATRIX_UID,
parentuid: DATRIX_PUID,
dirid: dirid,
parentobj: dirobj,
city: '上海市',
gps: '121.48789949,31.24916171',
isperdir: true,
userid: DATRIX_EXECUTE_ID,
debug: 'true'
};
$.ajax({
url: DATRIX_URL+DATRIX_CREATE_URI,
type: "POST",
dataType: "json",
data: data,
success: function (data) {
var back = data.result;
console.log(back);
/* var writeData = {
object: back.objid,
bucket: "itbasic",
length: fileSize,
offset: 0,
debug: true
}*/
fileWrite (fileSize, back.objid, fileSize, file, 0, back, fileId, fileText, type, button);
},
error : function(error) {
showAlert('上传失败', 'danger');
}
});
}
};
var fileWrite = function(uploadSize, objid, trueSize, file, start, back, fileId, fileText, type, button) {
var writeData = new FormData();
if(uploadSize <= 2 * 1024 * 1024) {
var fileSize = uploadSize;
} else {
var fileSize = 2 * 1024 * 1024;
}
var end = start * 1 + fileSize * 1;
var func = (file.mozSlice ? 'mozSlice' : (file.webkitSlice ? 'webkitSlice' : 'slice'));
var uploadFile = file[func](start, end);
writeData.append('object', objid); //var writeData = new FormData();
writeData.append('bucket', 'itbasic'); //上传文件用户id
writeData.append('length', fileSize); //filesize,上传文件内容
writeData.append('offset',start); //文件开始点
writeData.append('debug', true);
writeData.append('file', uploadFile); //文件内容
console.log(start, fileSize, uploadSize);
$.ajax({
url: DATRIX_URL+DATRIX_WRITE_URI,
type: "POST",
dataType: "json",
data: writeData,
processData: false,
contentType: false,
async : false,
success : function(data) {
//console.log(data);
uploadSize = uploadSize - fileSize;
console.log(uploadSize);
if (uploadSize*1 > 0) {
fileWrite(uploadSize, objid, trueSize, file, end, back, fileId, fileText, type, button);
return ;
}
var finishData = {
objectid:back.objid,
createuid:DATRIX_UID,
userid:DATRIX_EXECUTE_ID,
fileid:back.fileid,
debug:true
}
$.ajax({
url: DATRIX_URL+DATRIX_FINISH_URI,
type: "POST",
dataType: "json",
data: finishData,
async : false,
success : function() {
$('#'+button).removeAttr('disabled');
if (pro == 1) {
var f = {'fname':back.filename,'fid':back.fileid, 'objectid':back.objid};
uploadContractFile.push(f); console.log(uploadContractFile);
} else {
if (fileId) {
var file_id = $('#' + fileId).val();
var upload_text = $('#' + fileText).val() || '';
if (!file_id) {
file_id = back.fileid + ',' + back.filename;
$('#' + fileId).val(file_id);
} else {
file_id = file_id + ',' + back.fileid + ',' + back.filename;
$('#' + fileId).val(file_id);
}
if (!upload_text) {
upload_text = back.filename;
$('#' + fileText).val(upload_text);
} else {
upload_text = upload_text + ' , ' + back.filename;
$('#' + fileText).val(upload_text);
}
} else {
var upload_text = $(fileText).find('.upload_text').val() || '';
var html = '<a href="javascript:;" class="primary-link preview" data-filename="'+back.filename+'" data-fileid="'+back.fileid+'" data-objid="'+back.objid+'"> '+ back.filename +' </a>';
$(fileText).find('.file_preview').append(html);
if (!upload_text) {
upload_text = back.filename;
$(fileText).find('.upload_text').val(upload_text);
} else {
upload_text = upload_text + ' , ' + back.filename;
$(fileText).find('.upload_text').val(upload_text);
}
}
Model.addupload({
fileid: back.fileid,
filename: back.filename,
type: type,
objectid: back.objid
}, function (res) {
if (res.code === CODE_SUCCESS) {
} else if (res.code === CODE_ERROR) {
showAlert(res.msg, 'danger');
}
})
}
},
error: function() {
showAlert('上传失败', 'danger');
}
})
},
error : function() {
showAlert('上传失败', 'danger');
}
})
}
没维护了,以后接着看吧。
php 文件处理,主要包括文件的分割和合并
1 | function file_split($file,$block_size= 2 * 1024 * 1024){ |
php上传大文件有种就是先用php进行文件分割成小文件,然后小文件上传,然后上传到服务器上进行大文件合并。但有个问题就是php读取文件的fopen就8192字节,也就是8192B,一般上传文件都是4mb的上传,所以用的linux split分割文件后,放入文件夹里面,然后遍历文件夹,读取内容,写入操作的时候传入同一个objectid,往同一个文件里面写入