首页 > 其他分享 >js文件切片上传组件resumable.js使用

js文件切片上传组件resumable.js使用

时间:2024-10-30 16:32:39浏览次数:1  
标签:function console log resumable js getElementById video file 上传

接到一个媒体文件切片上传的需求,写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

相关文章

  • Javaweb 实验6 JSP内置对象
    我发现了有些人喜欢静静看博客不聊天呐,但是ta会点赞。这样的人呢帅气低调有内涵,美丽大方很优雅。说的就是你,不用再怀疑哦目的:掌握JSP内置对象的使用。理解JSP的作用域掌握JSP的表达式使用实验要求:完成实验题目要求提交实验报告,将代码和实验结果页面截图放入报告中第......
  • Mock.js基础
    1.mock.js的概念Mock.js是一个用于生成虚拟数据的JavaScript库,主要用于前端开发和测试。它可以帮助我们开发者在没有真实后端接口的情况下,模拟数据请求,方便进行开发和调试2.Mock.js的主要功能生成随机数据:Mock.js可以生成多种类型的随机数据,如字符串、数字、日期等。......
  • Nuxt.js 应用中的 imports:extend 事件钩子详解
    title:Nuxt.js应用中的imports:extend事件钩子详解date:2024/10/28updated:2024/10/28author:cmdragonexcerpt:imports:extend是Nuxt.js中的一个生命周期钩子,允许开发者在模块设置过程中扩展导入。使用此钩子,开发者可以灵活地管理和调整模块的导入配置,从而增......
  • Nuxt.js 应用中的 imports:dirs 事件钩子详解
    title:Nuxt.js应用中的imports:dirs事件钩子详解date:2024/10/30updated:2024/10/30author:cmdragonexcerpt:imports:dirs是Nuxt.js中的一个生命周期钩子,用于扩展导入目录。通过这个钩子,开发者可以灵活地添加、修改或删除项目中的导入目录,从而提高模块的可......
  • Nuxt.js 应用中的 imports:context 事件钩子详解
    title:Nuxt.js应用中的imports:context事件钩子详解date:2024/10/29updated:2024/10/29author:cmdragonexcerpt:imports:context是Nuxt.js中的一个生命周期钩子,主要用于在创建unimport上下文时调用。这个钩子为开发者提供了对模块导入上下文的操作能力,方......
  • Nuxt.js 应用中的 imports:dirs 事件钩子详解
    title:Nuxt.js应用中的imports:dirs事件钩子详解date:2024/10/30updated:2024/10/30author:cmdragonexcerpt:imports:dirs是Nuxt.js中的一个生命周期钩子,用于扩展导入目录。通过这个钩子,开发者可以灵活地添加、修改或删除项目中的导入目录,从而提高模块的可扩展性......
  • 基于node.js+vue基于Android的在线招聘平台的设计与实现(开题+程序+论文)计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于在线招聘平台的研究,现有研究主要集中在PC端和Web端,如基于B/S架构的在线招聘平台,实现了用户注册、职位发布、简历投递、面试安排等功能12。然而,专门......
  • 基于node.js+vue基于B_S的商务酒店网上预订管理系统(开题+程序+论文)计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于商务酒店网上预订系统的研究,现有研究主要集中在大型连锁酒店的预订系统,如Expedia、Booking.com等,这些系统通常采用C/S(客户端/服务器)架构,提供丰富的......
  • JavaScript 实现对 JSON 对象数组数据进行分页处理
    JavaScript实现对JSON对象数组数据进行分页处理在前端JavaScript中对JSON对象数组进行分页,可以通过以下方式实现:分页函数示例代码假设有一组JSON对象数据,比如一组用户信息:constdata=[{id:1,name:"Alice"},{id:2,name:"Bob"},{id:3,name:"......
  • Three.js 粒子系统教程构建炫酷的 3D 粒子效果
    开发领域:前端开发|AI应用|Web3D|元宇宙技术栈:JavaScript、React、ThreeJs、WebGL、Go经验经验:6年+前端开发经验,专注于图形渲染和AI技术开源项目:github晓智元宇宙、数字孪生引擎、前端面试题大家好!我是[晓智],一位热爱探索新技术的前端开发者,在这里分享前端和W......