接到一个媒体文件切片上传的需求,写demo记录下。
前端
<fieldset>
<legend>video preview</legend>
<div>
<video id="video-preview" controls muted height="112px" width="200px"></video>
<input type="file" id="video-upload" accept="video/*" />
</div>
</fieldset>
<script>
document.getElementById("video-upload").addEventListener("change", function (e) {
var file = e.target.files[0]; // 获取文件引用
var videoElement = document.getElementById("video-preview"); // 获取video元素
if (file && file.type.startsWith("video/")) {
// 检查文件是否为视频格式
var fileURL = URL.createObjectURL(file); // 创建文件URL
videoElement.src = fileURL; // 设置video的src属性为文件URL
} else {
alert("请选择一个视频文件。"); // 提示用户选择正确的文件类型
}
});
</script>
<fieldset>
<legend>video preview & upload</legend>
<div>
<video id="video-preview1" controls muted height="112px" width="200px"></video>
<video id="video-preview2" controls muted height="112px" width="200px"></video>
<a href="#" id="browseButton">Select files</a>
<a href="#" id="uploadButton" onclick="beginUpload()">Upload</a>
</div>
</fieldset>
<script src="../plugins/resumable.js"></script>
<script>
// 可实例化多个
const r = new Resumable({
target: "../../php-demos/upload.php",
chunkSize: 1 * 1024 * 1024,
testChunks: false, //打开后查看chunk是否存在的get请求先于发送chunks的post请求发起,返回大量的404
throttleProgressCallbacks: 1,
fileType: ["mp4"],
query: {},
maxFiles: 1,
});
r.assignBrowse(document.getElementById("browseButton"));
//文件上传成功
r.on("fileSuccess", function (file, msg) {
const msg_obj = JSON.parse(msg);
console.log("存储文件名", msg_obj["res_files"][0]);
document.getElementById("video-preview2").src = "http://localhost:3000/php-demos/temp/" + msg_obj["res_files"][0];
});
r.on("fileProgress", function (file) {
console.log("fileProgress", file);
});
r.on("fileAdded", function (file, event) {
console.log("fileAdded", event, file);
document.getElementById("video-preview1").src = URL.createObjectURL(file["file"]);
});
r.on("fileRetry", function (file) {
console.log("fileRetry", file);
});
r.on("fileError", function (file, message) {
console.log("fileError", file, message);
});
r.on("uploadStart", function () {
console.log("uploadStart");
});
r.on("complete", function () {
console.log("complete");
});
r.on("progress", function () {
console.log("progress");
});
r.on("error", function (message, file) {
console.log("error", message, file);
});
r.on("pause", function () {
console.log("pause");
});
r.on("cancel", function () {
console.log("cancel");
});
//上传
function beginUpload() {
r.upload();
}
</script>
<?php
date_default_timezone_set("Asia/Shanghai");
class Upload
{
public static $temp_path = "./temp/";
public static function write_log($str)
{
$log_str = "[" . date('Y-m-d H:i:s') . "]" . ": {$str}\r\n";
if (($fp = fopen(self::$temp_path . 'upload_log.txt', 'a+')) !== false) {
fputs($fp, $log_str);
fclose($fp);
}
}
public static function rrmdir($dir)
{
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir . "/" . $object) == "dir") {
self::rrmdir($dir . "/" . $object);
} else {
unlink($dir . "/" . $object);
}
}
}
reset($objects);
rmdir($dir);
}
}
public static function createFileFromChunks($temp_dir, $fileName, $chunkSize, $totalSize, $total_files)
{
$total_files_on_server_size = 0;
$temp_total = 0;
foreach (scandir($temp_dir) as $file) {
$temp_total = $total_files_on_server_size;
$tempfilesize = filesize($temp_dir . '/' . $file);
$total_files_on_server_size = $temp_total + $tempfilesize;
}
$res_filename = '';
if ($total_files_on_server_size >= $totalSize) {
$pos = strrpos($fileName, '.');
$name = substr($fileName, 0, $pos);
$ext = substr($fileName, $pos);
$filePath = $name . '-' . time() . '-' . rand(10, 99) . $ext;
$res_filename = $filePath;
if (($fp = fopen(self::$temp_path . $filePath, 'w')) !== false) {
for ($i = 1; $i <= $total_files; $i++) {
fwrite($fp, file_get_contents($temp_dir . '/' . $fileName . '.part' . $i));
self::write_log($fileName . ' writing chunk ' . $i);
}
fclose($fp);
} else {
self::write_log($fileName . ' cannot create the destination file');
return false;
}
if (rename($temp_dir, $temp_dir . '_UNUSED')) {
self::rrmdir($temp_dir . '_UNUSED');
} else {
self::rrmdir($temp_dir);
}
}
return $res_filename;
}
}
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (!(isset($_GET['resumableIdentifier']) && trim($_GET['resumableIdentifier']) != '')) {
$_GET['resumableIdentifier'] = '';
}
$temp_dir = Upload::$temp_path . $_GET['resumableIdentifier'];
if (!(isset($_GET['resumableFilename']) && trim($_GET['resumableFilename']) != '')) {
$_GET['resumableFilename'] = '';
}
if (!(isset($_GET['resumableChunkNumber']) && trim($_GET['resumableChunkNumber']) != '')) {
$_GET['resumableChunkNumber'] = '';
}
$chunk_file = $temp_dir . '/' . $_GET['resumableFilename'] . '.part' . $_GET['resumableChunkNumber'];
if (file_exists($chunk_file)) {
header("HTTP/1.0 200 Ok");
} else {
header("HTTP/1.0 404 Not Found");
}
}
$res_files = [];
if (!empty($_FILES)) {
foreach ($_FILES as $file) {
$res_filename = '';
if ($file['error'] != 0) {
Upload::write_log('error ' . $file['error'] . ' in file ' . $_POST['resumableFilename']);
continue;
}
if (isset($_POST['resumableIdentifier']) && trim($_POST['resumableIdentifier']) != '') {
$temp_dir = Upload::$temp_path . $_POST['resumableIdentifier'];
}
$dest_file = $temp_dir . '/' . $_POST['resumableFilename'] . '.part' . $_POST['resumableChunkNumber'];
if (!is_dir($temp_dir)) {
mkdir($temp_dir, 0777, true);
}
if (!move_uploaded_file($file['tmp_name'], $dest_file)) {
Upload::write_log('Error saving (move_uploaded_file) chunk ' . $_POST['resumableChunkNumber'] . ' for file ' . $_POST['resumableFilename']);
} else {
$res_filename = Upload::createFileFromChunks($temp_dir, $_POST['resumableFilename'], $_POST['resumableChunkSize'], $_POST['resumableTotalSize'], $_POST['resumableTotalChunks']);
}
$res_files[] = $res_filename;
}
}
echo json_encode(['res_files' => $res_files]);
视频大小4MB左右,测试过30MB左右的文件,上传速度也是非常快的。
标签:function,console,log,resumable,js,getElementById,video,file,上传 From: https://www.cnblogs.com/caroline2016/p/18516066