vue文件夹上传组件选哪个好?

2023-11-05

一、 功能性需求与非功能性需求

要求操作便利,一次选择多个文件和文件夹进行上传;
支持PC端全平台操作系统,Windows,Linux,Mac

支持文件和文件夹的批量下载,断点续传。刷新页面后继续传输。关闭浏览器后保留进度信息。

支持文件夹批量上传下载,服务器端保留文件夹层级结构,服务器端文件夹层级结构与本地相同。

支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验;
支持文件夹上传,文件夹中的文件数量达到1万个以上,且包含层级结构。

支持断点续传,关闭浏览器或刷新浏览器后仍然能够保留进度。

支持文件夹结构管理,支持新建文件夹,支持文件夹目录导航

交互友好,能够及时反馈上传的进度;

服务端的安全性,不因上传文件功能导致JVM内存溢出影响其他功能使用;

最大限度利用网络上行带宽,提高上传速度;


二、 设计分析

对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是不可取,很容易导致内存问题。所以对于大文件上传,采用切块分段上传

从上传的效率来看,利用多线程并发上传能够达到最大效率。


三、解决方案:

文件上传页面的前端可以选择使用一些比较好用的上传组件,例如百度的开源组件WebUploader,泽优软件的up6,这些组件基本能满足文件上传的一些日常所需功能,如异步上传文件,文件夹,拖拽式上传,黏贴上传,上传进度监控,文件缩略图,甚至是大文件断点续传,大文件秒传。 

 

在web项目中上传文件夹现在已经成为了一个主流的需求。在OA,或者企业ERP系统中都有类似的需求。上传文件夹并且保留层级结构能够对用户行成很好的引导,用户使用起来也更方便。能够提供更高级的应用支撑。

文件夹数据表结构

CREATE TABLE IF NOT EXISTS `up6_folders` (

  `f_id`               char(32) NOT NULL ,

  `f_nameLoc`               varchar(255) default '',

  `f_pid`                   char(32) default '',

  `f_uid`                   int(11) default '0',

  `f_lenLoc`           bigint(19) default '0',

  `f_sizeLoc`               varchar(50) default '0',

  `f_pathLoc`               varchar(255) default '',

  `f_pathSvr`               varchar(255) default '',

  `f_pathRel`               varchar(255) default '',

  `f_folders`               int(11) default '0',

  `f_fileCount`        int(11) default '0',

  `f_filesComplete`    int(11) default '0',

  `f_complete`              tinyint(1) default '0',

  `f_deleted`               tinyint(1) default '0',

  `f_time`                  timestamp NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,

  `f_pidRoot`               char(32) default '',

  PRIMARY KEY  (`f_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

文件数据表结构

CREATE TABLE IF NOT EXISTS `up6_files` (

  `f_id`               char(32) NOT NULL,

  `f_pid`                   char(32) default '',        /*父级文件夹ID*/

  `f_pidRoot`               char(32) default '',        /*根级文件夹ID*/

  `f_fdTask`           tinyint(1) default '0',     /*是否是一条文件夹信息*/

  `f_fdChild`               tinyint(1) default '0',     /*是否是文件夹中的文件*/

  `f_uid`                   int(11) default '0',

  `f_nameLoc`               varchar(255) default '',    /*文件在本地的名称(原始文件名称)*/

  `f_nameSvr`               varchar(255) default '',    /*文件在服务器的名称*/

  `f_pathLoc`               varchar(512) default '',    /*文件在本地的路径*/

  `f_pathSvr`               varchar(512) default '',    /*文件在远程服务器中的位置*/

  `f_pathRel`               varchar(512) default '',

  `f_md5`                   varchar(40) default '',     /*文件MD5*/

  `f_lenLoc`           bigint(19) default '0',     /*文件大小*/

  `f_sizeLoc`               varchar(10) default '0',    /*文件大小(格式化的)*/

  `f_pos`                   bigint(19) default '0',     /*续传位置*/

  `f_lenSvr`           bigint(19) default '0',     /*已上传大小*/

  `f_perSvr`           varchar(7) default '0%',    /*已上传百分比*/

  `f_complete`              tinyint(1) default '0',     /*是否已上传完毕*/

  `f_time`                  timestamp NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,

  `f_deleted`               tinyint(1) default '0',

  `f_scan`                  tinyint(1) default '0',

  PRIMARY KEY  (`f_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

该项目核心就是文件分块上传。前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题。

* 如何分片;

* 如何合成一个文件;

* 中断了从哪个分片开始。

如何分,利用强大的js库,来减轻我们的工作,市场上已经能有关于大文件分块的轮子,虽然程序员的天性曾迫使我重新造轮子。但是因为时间的关系还有工作的关系,我只能罢休了。最后我选择了百度的WebUploader来实现前端所需。

如何合,在合之前,我们还得先解决一个问题,我们如何区分分块所属那个文件的。刚开始的时候,我是采用了前端生成了唯一uuid来做文件的标志,在每个分片请求上带上。不过后来在做秒传的时候我放弃了,采用了Md5来维护分块和文件关系。

在服务端合并文件,和记录分块的问题,在这方面其实行业已经给了很好的解决方案了。参考迅雷,你会发现,每次下载中的时候,都会有两个文件,一个文件主体,另外一个就是文件临时文件,临时文件存储着每个分块对应字节位的状态。

这些都是需要前后端密切联系才能做好,前端需要根据固定大小对文件进行分片,并且请求中要带上分片序号和大小。前端发送请求顺利到达后台后,服务器只需要按照请求数据中给的分片序号和每片分块大小(分片大小是固定且一样的)算出开始位置,与读取到的文件片段数据,写入文件即可。

为了便于开发,我 将服务端的业务逻辑进行了如下划分,分成初始化,块处理,文件上传完毕等。

服务端的业务逻辑模块如下

 

功能分析:

文件夹生成模块

文件夹上传完毕后由服务端进行扫描代码如下

public class fd_scan

{

    DbHelper db;

    Connection con;

    PreparedStatement cmd_add_f = null;

    PreparedStatement cmd_add_fd = null;

    public FileInf root = null;//根节点

   

    public fd_scan()

    {

        this.db = new DbHelper();

        this.con = this.db.GetCon();       

    }

   

    public void makeCmdF()

    {

        StringBuilder sb = new StringBuilder();

        sb.append("insert into up6_files (");

        sb.append(" f_id");//1

        sb.append(",f_pid");//2

        sb.append(",f_pidRoot");//3

        sb.append(",f_fdTask");//4

        sb.append(",f_fdChild");//5

        sb.append(",f_uid");//6

        sb.append(",f_nameLoc");//7

        sb.append(",f_nameSvr");//8

        sb.append(",f_pathLoc");//9

        sb.append(",f_pathSvr");//10

        sb.append(",f_pathRel");//11

        sb.append(",f_md5");//12

        sb.append(",f_lenLoc");//13

        sb.append(",f_sizeLoc");//14

        sb.append(",f_lenSvr");//15

        sb.append(",f_perSvr");//16

        sb.append(",f_complete");//17

       

        sb.append(") values(");

       

        sb.append(" ?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(")");

 

        try {

            this.cmd_add_f = this.con.prepareStatement(sb.toString());

            this.cmd_add_f.setString(1, "");//id

            this.cmd_add_f.setString(2, "");//pid

            this.cmd_add_f.setString(3, "");//pidRoot

            this.cmd_add_f.setBoolean(4, true);//fdTask

            this.cmd_add_f.setBoolean(5, false);//f_fdChild

            this.cmd_add_f.setInt(6, 0);//f_uid

            this.cmd_add_f.setString(7, "");//f_nameLoc

            this.cmd_add_f.setString(8, "");//f_nameSvr

            this.cmd_add_f.setString(9, "");//f_pathLoc

            this.cmd_add_f.setString(10, "");//f_pathSvr

            this.cmd_add_f.setString(11, "");//f_pathRel

            this.cmd_add_f.setString(12, "");//f_md5

            this.cmd_add_f.setLong(13, 0);//f_lenLoc

            this.cmd_add_f.setString(14, "");//f_sizeLoc

            this.cmd_add_f.setLong(15, 0);//f_lenSvr            

            this.cmd_add_f.setString(16, "");//f_perSvr

            this.cmd_add_f.setBoolean(17, true);//f_complete

        } catch (SQLException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

   

    public void makeCmdFD()

    {

        StringBuilder sb = new StringBuilder();

        sb.append("insert into up6_folders (");

        sb.append(" f_id");//1

        sb.append(",f_pid");//2

        sb.append(",f_pidRoot");//3

        sb.append(",f_nameLoc");//4

        sb.append(",f_uid");//5

        sb.append(",f_pathLoc");//6

        sb.append(",f_pathSvr");//7

        sb.append(",f_pathRel");//8

        sb.append(",f_complete");//9

        sb.append(") values(");//

        sb.append(" ?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(",?");

        sb.append(")");

 

        try {

            this.cmd_add_fd = this.con.prepareStatement(sb.toString());

            this.cmd_add_fd.setString(1, "");//id

            this.cmd_add_fd.setString(2, "");//pid

            this.cmd_add_fd.setString(3, "");//pidRoot

            this.cmd_add_fd.setString(4, "");//name

            this.cmd_add_fd.setInt(5, 0);//f_uid

            this.cmd_add_fd.setString(6, "");//pathLoc

            this.cmd_add_fd.setString(7, "");//pathSvr

            this.cmd_add_fd.setString(8, "");//pathRel

            this.cmd_add_fd.setBoolean(9, true);//complete

        } catch (SQLException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

   

    protected void GetAllFiles(FileInf inf,String root)

    {

        File dir = new File(inf.pathSvr);

        File [] allFile = dir.listFiles();

        for(int i = 0; i < allFile.length; i++)

        {

            if(allFile[i].isDirectory())

            {

                FileInf fd = new FileInf();

                String uuid = UUID.randomUUID().toString();

                uuid = uuid.replace("-", "");

                fd.id = uuid;

                fd.pid = inf.id;

                fd.pidRoot = this.root.id;

                fd.nameSvr = allFile[i].getName();

                fd.nameLoc = fd.nameSvr;

                fd.pathSvr = allFile[i].getPath();

                fd.pathSvr = fd.pathSvr.replace("\\", "/");

                fd.pathRel = fd.pathSvr.substring(root.length() + 1);

                fd.perSvr = "100%";

                fd.complete = true;

                this.save_folder(fd);

               

                this.GetAllFiles(fd, root);

            }

            else

            {

                FileInf fl = new FileInf();

                String uuid = UUID.randomUUID().toString();

                uuid = uuid.replace("-", "");

                fl.id = uuid;

                fl.pid = inf.id;

                fl.pidRoot = this.root.id;

                fl.nameSvr = allFile[i].getName();

                fl.nameLoc = fl.nameSvr;

                fl.pathSvr = allFile[i].getPath();

                fl.pathSvr = fl.pathSvr.replace("\\", "/");

                fl.pathRel = fl.pathSvr.substring(root.length() + 1);

                fl.lenSvr = allFile[i].length();

                fl.lenLoc = fl.lenSvr;

                fl.perSvr = "100%";

                fl.complete = true;

                this.save_file(fl);

            }

        }

    }

   

    protected void save_file(FileInf f)

    {      

        try {

            this.cmd_add_f.setString(1, f.id);//id

            this.cmd_add_f.setString(2, f.pid);//pid

            this.cmd_add_f.setString(3, f.pidRoot);//pidRoot

            this.cmd_add_f.setBoolean(4, f.fdTask);//fdTask

            this.cmd_add_f.setBoolean(5, true);//f_fdChild

            this.cmd_add_f.setInt(6, f.uid);//f_uid

            this.cmd_add_f.setString(7, f.nameLoc);//f_nameLoc

            this.cmd_add_f.setString(8, f.nameSvr);//f_nameSvr

            this.cmd_add_f.setString(9, f.pathLoc);//f_pathLoc

            this.cmd_add_f.setString(10, f.pathSvr);//f_pathSvr

            this.cmd_add_f.setString(11, f.pathRel);//f_pathRel

            this.cmd_add_f.setString(12, f.md5);//f_md5

            this.cmd_add_f.setLong(13, f.lenLoc);//f_lenLoc

            this.cmd_add_f.setString(14, f.sizeLoc);//f_sizeLoc

            this.cmd_add_f.setLong(15, f.lenSvr);//f_lenSvr        

            this.cmd_add_f.setString(16, f.perSvr);//f_perSvr

            this.cmd_add_f.setBoolean(17, f.complete);//f_complete

            this.cmd_add_f.executeUpdate();

        } catch (SQLException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }//

    }

   

    protected void save_folder(FileInf f)

    {

        try {

            this.cmd_add_fd.setString(1, f.id);//id

            this.cmd_add_fd.setString(2, f.pid);//pid

            this.cmd_add_fd.setString(3, f.pidRoot);//pidRoot

            this.cmd_add_fd.setString(4, f.nameSvr);//name

            this.cmd_add_fd.setInt(5, f.uid);//f_uid

            this.cmd_add_fd.setString(6, f.pathLoc);//pathLoc

            this.cmd_add_fd.setString(7, f.pathSvr);//pathSvr

            this.cmd_add_fd.setString(8, f.pathRel);//pathRel

            this.cmd_add_fd.setBoolean(9, f.complete);//complete

            this.cmd_add_fd.executeUpdate();

        } catch (SQLException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

   

    public void scan(FileInf inf, String root) throws IOException, SQLException

    {

        this.makeCmdF();

        this.makeCmdFD();

        this.GetAllFiles(inf, root);

        this.cmd_add_f.close();

        this.cmd_add_fd.close();

        this.con.close();

    }

}

 

分块上传,分块处理逻辑应该是最简单的逻辑了,up6已经将文件进行了分块,并且对每个分块数据进行了标识,这些标识包括文件块的索引,大小,偏移,文件MD5,文件块MD5(需要开启)等信息,服务端在接收这些信息后便可以非常方便的进行处理了。比如将块数据保存到分布式存储系统中

分块上传可以说是我们整个项目的基础,像断点续传、暂停这些都是需要用到分块。

分块这块相对来说比较简单。前端是采用了webuploader,分块等基础功能已经封装起来,使用方便。

借助webUpload提供给我们的文件API,前端就显得异常简单。

前台HTML模板

this.GetHtmlFiles = function()

{

     var acx = "";

     acx += '<div class="file-item" id="tmpFile" name="fileItem">\

                <div class="img-box"><img name="file" src="js/file.png"/></div>\

                   <div class="area-l">\

                       <div class="file-head">\

                            <div name="fileName" class="name">HttpUploader程序开发.pdf</div>\

                            <div name="percent" class="percent">(35%)</div>\

                            <div name="fileSize" class="size" child="1">1000.23MB</div>\

                    </div>\

                       <div class="process-border"><div name="process" class="process"></div></div>\

                       <div name="msg" class="msg top-space">15.3MB 20KB/S 10:02:00</div>\

                   </div>\

                   <div class="area-r">\

                    <span class="btn-box" name="cancel" title="取消"><img name="stop" src="js/stop.png"/><div>取消</div></span>\

                    <span class="btn-box hide" name="post" title="继续"><img name="post" src="js/post.png"/><div>继续</div></span>\

                       <span class="btn-box hide" name="stop" title="停止"><img name="stop" src="js/stop.png"/><div>停止</div></span>\

                       <span class="btn-box hide" name="del" title="删除"><img name="del" src="js/del.png"/><div>删除</div></span>\

                   </div>';

     acx += '</div>';

     acx += '<div class="file-item" name="folderItem">\

                   <div class="img-box"><img name="folder" src="js/folder.png"/></div>\

                   <div class="area-l">\

                       <div class="file-head">\

                            <div name="fileName" class="name">HttpUploader程序开发.pdf</div>\

                            <div name="percent" class="percent">(35%)</div>\

                            <div name="fileSize" class="size" child="1">1000.23MB</div>\

                    </div>\

                       <div class="process-border top-space"><div name="process" class="process"></div></div>\

                       <div name="msg" class="msg top-space">15.3MB 20KB/S 10:02:00</div>\

                   </div>\

                   <div class="area-r">\

                    <span class="btn-box" name="cancel" title="取消"><img name="stop" src="js/stop.png"/><div>取消</div></span>\

                    <span class="btn-box hide" name="post" title="继续"><img name="post" src="js/post.png"/><div>继续</div></span>\

                       <span class="btn-box hide" name="stop" title="停止"><img name="stop" src="js/stop.png"/><div>停止</div></span>\

                       <span class="btn-box hide" name="del" title="删除"><img name="del" src="js/del.png"/><div>删除</div></span>\

                   </div>';

     acx += '</div>';

     acx += '<div class="files-panel" name="post_panel">\

                   <div name="post_head" class="toolbar">\

                       <span class="btn" name="btnAddFiles">选择多个文件</span>\

                       <span class="btn" name="btnAddFolder">选择文件夹</span>\

                       <span class="btn" name="btnPasteFile">粘贴文件和目录</span>\

                       <span class="btn" name="btnSetup">安装控件</span>\

                   </div>\

                   <div class="content" name="post_content">\

                       <div name="post_body" class="file-post-view"></div>\

                   </div>\

                   <div class="footer" name="post_footer">\

                       <span class="btn-footer" name="btnClear">清除已完成文件</span>\

                   </div>\

              </div>';

     return acx;

};

 

分则必合。把大文件分片了,但是分片了就没有原本文件功能,所以我们要把分片合成为原本的文件。我们只需要把分片按原本位置写入到文件中去。因为前面原理那一部我们已经讲到了,我们知道分块大小和分块序号,我就可以知道该分块在文件中的起始位置。所以这里使用RandomAccessFile是明智的,RandomAccessFile能在文件里面前后移动。但是在andomAccessFile的绝大多数功能,已经被JDK1.4的NIO的“内存映射文件(memory-mapped files)”取代了。我在该项目中分别写了使用RandomAccessFile与MappedByteBuffer来合成文件。分别对应的方法是uploadFileRandomAccessFile和uploadFileByMappedByteBuffer。两个方法代码如下。

秒传功能

服务端逻辑

秒传功能,相信大家都体现过了,网盘上传的时候,发现上传的文件秒传了。其实原理稍微有研究过的同学应该知道,其实就是检验文件MD5,记录下上传到系统的文件的MD5,在一个文件上传前先获取文件内容MD5值或者部分取值MD5,然后在匹配系统上的数据。

Breakpoint-http实现秒传原理,客户端选择文件之后,点击上传的时候触发获取文件MD5值,获取MD5后调用系统一个接口(/index/checkFileMd5),查询该MD5是否已经存在(我在该项目中用redis来存储数据,用文件MD5值来作key,value是文件存储的地址。)接口返回检查状态,然后再进行下一步的操作。相信大家看代码就能明白了。

嗯,前端的MD5取值也是用了webuploader自带的功能,这还是个不错的工具。

控件计算完文件MD5后会触发md5_complete事件,并传值md5,开发者只需要处理这个事件即可,

 

断点续传

up6已经自动对断点续传进行了处理,不需要开发都再进行单独的处理。

在f_post.jsp中接收这些参数,并进行处理,开发者只需要关注业务逻辑,不需要关注其它的方面。

 

断点续传,就是在文件上传的过程中发生了中断,人为因素(暂停)或者不可抗力(断网或者网络差)导致了文件上传到一半失败了。然后在环境恢复的时候,重新上传该文件,而不至于是从新开始上传的。

前面也已经讲过,断点续传的功能是基于分块上传来实现的,把一个大文件分成很多个小块,服务端能够把每个上传成功的分块都落地下来,客户端在上传文件开始时调用接口快速验证,条件选择跳过某个分块。

实现原理,就是在每个文件上传前,就获取到文件MD5取值,在上传文件前调用接口(/index/checkFileMd5,没错也是秒传的检验接口)如果获取的文件状态是未完成,则返回所有的还没上传的分块的编号,然后前端进行条件筛算出哪些没上传的分块,然后进行上传。

当接收到文件块后就可以直接写入到服务器的文件中

这是文件夹上传完后的效果

这是文件夹上传完后在服务端的存储结构

参考文章:http://blog.ncmem.com/wordpress/2019/08/12/java-http%E5%A4%A7%E6%96%87%E4%BB%B6%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0%E4%B8%8A%E4%BC%A0/

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue文件夹上传组件选哪个好? 的相关文章

  • 经典卷积神经网络——resnet

    resnet 前言 一 resnet 二 resnet网络结构 三 resnet18 1 导包 2 残差模块 2 通道数翻倍残差模块 3 rensnet18模块 4 数据测试 5 损失函数 优化器 6 加载数据集 数据增强 7 训练数据 8
  • linux安装python3以及pip过程,遇到的错误处理

    需要自己搭建环境 没想到的是基本的安装python3过程过程就踩了很多坑 希望对别人有帮助 参考 https www centoschina cn course config 11027 html 1 下载相应python3 7解释器htt
  • Unity—3D数学基础

    今天用了小半天时间初步了解3D数学基础 明天开始进入unity游戏脚本编写 每日一句 人间骄阳正好 风过林梢 彼时我们正当年少 目录 3D坐标系 全局 世界 坐标系 局部 模型 物体 坐标系 相机坐标系 屏幕坐标系 向量 向量的运算 Vec
  • div滚动到顶部或者底部触发分页查询方法

    如聊天界面 滚动到顶部触发分页 div标签里添加滚动事件 scroll passive getScrollUser event 方法 getScroll event if event target scrollTop 0 this chat
  • 6.824分布式

    MapReduce 例子加深理解 你的工作是实现一个分布式的MapReduce 包括两个程序 master 和 worker 只有一个master进程 以及 一个或多个worker进程并行执行 在真实的系统中 工作人员将在许多不同的机器上运
  • 【安全工具】Web漏洞扫描十大工具

    Web漏洞扫描十大工具 Acunetix Web Vulnerability Scanner 简称AwVS AwVS是一款知名的Web网络漏洞扫描工具 它通过网络爬虫测试你的网站安全 检测流行安全漏洞 a 自动的客户端脚本分析器 允许对Aj
  • 关于springBoot如何配置双数据源

    前言 本文采用springBoot 配置类的方式简单配置Mysql PostgreSql双数据源 1 首先导入需要的pom依赖
  • 配置测试

    1 配置测试 configuration testing 配置测试是指使用各种硬件来测试软件运行的过程 2 基于Windows的PC机包括 个人计算机 部件 系统主板 内部板卡和其他内部设备 外设 接口 可选项和内存 设备驱动程序 3 配置
  • 轻松理解转置卷积(transposed convolution)或反卷积(deconvolution)

    本译文很大程度上保留了原文原貌 并添加了细节便于理解 各种指代 在CNN中 转置卷积是一种上采样 up sampling 的常见方法 如果你不清楚转置卷积是怎么操作的 那么就来读读这篇文章吧 本文的notebook代码在Github 上采样
  • Redis——数据结构介绍

    Redis是一个key value的数据库 key一般是String类型 不过value的类型是多样的 String hello word Hash name Jack age 21 List A gt B gt C gt D Set A
  • SaltStack 自动化运维详解

    一 自动化运维工具对比 使用所需软件配置单个服务器是一项相当简单的任务 但是 如果许多服务器需要安装相同或相似的软件和配置 则该过程将需要大量的工时才能完成 这会耗尽您本已紧张的资源 如果没有某种形式的自动化 这项任务几乎无法完成 考虑到这
  • 关于SpringMVC返回date的格式问题

    Spring 项目中 java的util date和java time类型的日期 返回到前端的时候 默认的序列化方式显示的是标准格式 为了能够正确的显示想要的时间 可以使用jackson指定时间的格式 访问我的个人网站获取更多文章 数据库的
  • 汽车的操作系统AUTOSAR

    汽车软件开发autosar 01汽车相关知识 汽车发展三大趋势 电动化 智能化 网联化 1 电动化 底层支撑 网联化的驱动力 2 智能化 人工智能借助软硬融合带来功能升级 体验升级 安全升级 3 网联化 5G的应用场景 让汽车与人 车 物的
  • golang实现p2p之UDP打洞

    当今互联网到处存在着一些中间件 MIddleBoxes 如NAT和防火墙 导致两个 不在同一内网 中的客户端无法直接通信 这些问题即便是到了IPV6时代也会存在 因为即使不需要NAT 但还有其他中间件如防火墙阻挡了链接的建立 目前部署的中间
  • spring boot毕业生跟踪调查管理系统 毕业设计源码论文+答辩PPT

    答辩PPT 论文 springboot毕业生跟踪调查管理系统 摘 要 信息化社会内需要与之针对性的信息获取途径 但是途径的扩展基本上为人们所努力的方向 由于站在的角度存在偏差 人们经常能够获得不同类型信息 这也是技术最为难以攻克的课题 针对
  • CF 1843F2 - Omsk Metro (hard version)

    CF 1843F2 Omsk Metro hard version 题目描述 给定 n n n 个节点的有根树 根节点为 1 1 1 每个节点上有权值 0
  • asp.net中,<%#%>,<%=%>和<%%>分别是什么意思,有什么区别

    在asp net中经常出现包含这种形式的html代码 总的来说包含下面这样几种格式 一 这种格式实际上就是和asp的用法一样的 只是asp中里面是vbscript或者javascript代码 而在asp net中是 net平台下支持的语言
  • 使用ScriptableObject代替部分配置表的坑点

    1 使用ScriptableObject代替部分配置表的坑点 2 加载配置内存过大问题 3 URP的UI在Android模型器下比在真机上暗 4 Unity在Windows上第一次运行Play启动很慢 5 如何正确卸载UnityWebReq
  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一

随机推荐

  • 【2023】数据库sql增删改查执行命令汇总(配合详细举例)

    一 单表查询 数据查询语言 专门用于查找表中的数据 select from emp 关键字 select from 表名 查询表中的所有数据 source 导入文件的文件地址 文件名称 导入dump数据 结尾不能加 号 mysql的数据备份
  • 【git】全局配置和单个仓库的用户名邮箱配置

    Git全局配置和单个仓库的用户名邮箱配置 学习git的时候 大家刚开始使用之前都配置了一个全局的用户名和邮箱 git config global user name github s Name git config global user
  • 领导力大挑战

    author skate time 2012 10 13 在实施Scrum的项目中 Scrum Master对于团队而言是相当关键的 担当着推动整个团队完成产品所有者既定目标的角色 Scrum Master的主要工作是替团队扫清前进的障碍
  • 树莓派交叉编译如何处理软连接

    软链接有点类似windows的快捷方式 添加软连接 ln s libfilename so 2 5 libfilenameso ln是指令 s是参数 so 2 5是要被链接的文件 so是软连接名字 生成硬链接 去掉 s
  • STM32编译错误

    output test axf Error L6218E Undefined symbol SystemInit referred from startup stm32f10x hd o Not enough information to
  • 现代计算机从0到1:冯·诺依曼计算机

    最近打算开始写博客 在想一开始该写什么好呢 突然灵光一现 关于计算机当然就是现代计算机之父 我们今天就来聊一下现代计算机之父 约翰 冯 诺依曼 John Von Nouma 1903 1957 美藉匈牙利人 1903年12月28日生于匈牙利
  • Linux驱动开发 通过字符设备驱动分步注册方式编写LED驱动

    通过字符设备驱动分步注册方式编写LED驱动 完成设备文件和设备的绑定 head h ifndef HEAD H define HEAD H typedef struct unsigned int MODER unsigned int OTY
  • STM32实战总结:HAL之IAP

    我们学习单片机一般都是从51开始的 51单片机烧录程序通常是使用烧录软件如STC ISP 这种方式 通过串口连接单片机 选择一个合适的波特率就可以烧录了 后来学习STM32 编程时使用KEIL软件自带的下载按钮就能下载程序 方便了不少 但需
  • ssh 连接到docker内,环境变量发生变化的解决方法(改)

    参考 https blog csdn net m0 59029800 article details 125479518 上述方法的问题 环境变量中存在空格时出错 解决方法 更改字段分隔符 使之仅仅遇到换行时分割 OLD IFS IFS n
  • 19、ddt数据驱动测试

    背景 设计测试用例是 有些测试用例只是参数数据输入不一样而已 比如登录时 需要经常切换账号 而操作基本是一样的 如果用例重复去写操作过程会导致很多冗余的代码 1 安装ddt pip install ddt 2 原理 测试数据为多个字典的li
  • UVA 1601 The Morning after Halloween

    https vjudge net problem UVA 1601 题目 你在游乐场的鬼屋里当操作员 专门控制鬼屋里的机器人 某日没事干的出题人把这些机器人搬到了其他地方 你需要在最短的时间内遥控机器人让他们回到原位 所有机器人都可以同时在
  • 超级无敌简单题(鸽子数)

    欢迎访问https blog csdn net lxt Lucia 宇宙第一小仙女 o 萌量爆表求带飞 o dalao们点个关注呗 我只是一条可爱哒分界线 一 问题 Description 通常来说 题面短的题目一般都比较难 所以我要把题面
  • 【线性回归——从简单构建到实现数据预测】

    深度学习与神经网络day03 线性回归 一 简单的线性回归 1 1 数据集的构建 1 2 模型构建 1 3 损失函数 1 4 模型优化 1 5 模型训练 1 6 模型评估 1 7 样本数量和正则化系数的影响 二 多项式回归 1 1 数据集的
  • Qt(day1)

    思维导图 Qt实现第一个web的基础页面 include mywnd h include ui mywnd h include
  • IP协议-NAT机制(理解网络结构的关键要点)

    前言 我们现在使用得最多的IP协议版本是IPv4 IPv4是4个字节 32位 也就是说我们的IP地址最多就只有2 32 42亿 个 在日常生活中 我们需要联网的设备都需要有IP地址才能进行通讯 很明显现在42亿个IP地址已经完全不足以满足我
  • 矩阵乘法的本质是什么

    作者 知乎用户 链接 https www zhihu com question 21351965 answer 31050145 本题目前下面的解释都是线性代数教材上的各种定义 但都太过复杂了 我尝试写一个浅显的解释 小明今天要做饭 消耗2
  • 解决servlet filter中if语句无效问题

    今天写代码学习filter时 遇到了一件很奇怪的事情 就是当在jsp中同时提交文件和一个text组件时 servlet中的if语句无法返回true 代码如下 这是jsp代码
  • html三个组成部分组成部分,JavaScript组成(三个组成部分)

    JavaScript主要包括三部分 1 ECMAScript JavaScript的核心 仅仅是一个描述 定义了脚本语言的所有属性 方法和对象 具体地 ECMAscript描述了以下内容 语法 类型 语句 关键字 保留字 运算符 对象 每个
  • .cu的cuda程序的kernel函数中调用std函数无法编译的问题解决; error: calling a constexpr __host__ function

    引言 本人初学cuda编程 在jetson nano 4G上想实现sliced wasserstein distance的各个slice并行加速计算 遇到一些问题和解决方案 记录在此 基础知识 在cuda编程中 cpu称作host gpu称
  • vue文件夹上传组件选哪个好?

    一 功能性需求与非功能性需求 要求操作便利 一次选择多个文件和文件夹进行上传 支持PC端全平台操作系统 Windows Linux Mac 支持文件和文件夹的批量下载 断点续传 刷新页面后继续传输 关闭浏览器后保留进度信息 支持文件夹批量上