当前位置: 首页 > news >正文

java文件上传

导入jar包,或者maven

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version>
</dependency>

使用类的介绍

【文件上传的注意事项】
1. 为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于web-inf目录下。
2. 为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
3. 要限制上传文件的最大值。
4. 可以限制上传文件的类型,在收到上传文件名时,判断后级名是否合法。


【需要用到的类详解】
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个filetem对象,在使用ServletFileUpload对象解析请求时需要DiskFileltemFactory对象。所以,我们需要在进行解析工作前构造好DikFileltemFactory对象,通过ServletFileUpload对象的构造方法或setFileltemFactory( ) 设置ServletFileUpload对象的fileltemFactory属性。

Fileltem类

在HTML页面input必须有 name<input type="file" name="filename">

表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为 multipart / form-data

浏览器表单的类型如果为 multipart / form-data, 在服务器想获取数据就要通过流

【常用方法介绍】

//isFormField 方法用于判断FileItem类对象封装的数据是一个普通文本表单
//还是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFlormField();//getFieldName方法用于返回表单标签name属性的值
String getFieldName();
//getString 方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();//getName 方法用于获得文件上传字段中得文件名
String getName();//以流得形式返回上传文件得数据内容
InputStream getInputStream();//delete方法用来清空FileItem类对象中存放的主体内容
//如果主题内容被保存在临时文件中,delete方法将删除临时文件
void delete();

ServletFileUpload类

ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个Fileltem对象中,使用其paraRequest(HttpServletRequest)方法可以将通过表单中每一个HTML标签提交的数据封装成一个Fileltem对象,然后以List列表的形式返回,使用该方法处理上传文件简单易用。

代码编写

UploadFileServlet

packagecom.yatian.servlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.util.List;importjava.util.UUID;importorg.apache.commons.fileupload.FileItem;importorg.apache.commons.fileupload.FileUploadException;importorg.apache.commons.fileupload.ProgressListener;importorg.apache.commons.fileupload.disk.DiskFileItemFactory;importorg.apache.commons.fileupload.servlet.ServletFileUpload;public class FileServlet extendsHttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throwsjavax.servlet.ServletException, IOException {//判断上传的表单是普通表单还是带文件的表单,是返回true,否返回false;

if (!ServletFileUpload.isMultipartContent(request)){return;//如果这是一个普通文件我们直接返回

}//如果通过了这个if,说明我们的表单是带文件上传的//创建上传文件的保存目录,为了安全建议在WEB-INF目录下,用户无法访问

String uploadpath = this.getServletContext().getRealPath("WEB-INF/Upload");//获取上传文件的保存路径

File uploadfile = newFile(uploadpath);if (!uploadfile.exists()){

uploadfile.mkdir();//如果目录不存在就创建这样一个目录

}/*//临时文件

//临时路径,如果上传的文件超过预期的大小,我们将它存放到一个临时目录中,过几天自动删除,或者提醒用户转存为永久

String tmppath = this.getServletContext().getRealPath("WEB-INF/tmp");

File file = new File(tmppath);

if (!file.exists()){

file.mkdir();//如果目录不存在就创建这样临时目录

}*/

//处理上传的文件一般需要通过流来获取,我们可以通过request.getInputstream(),原生态文件上传流获取,十分麻烦//但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件;

try{//1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小

DiskFileItemFactory factory =gteDiskFileItemFactory(file);//2、获取ServletFileUpload

ServletFileUpload upload =getServletFileUpload(factory);//3、处理上传文件

String msg =uploadParseRequest(upload,request,uploadpath);//Servlet请求转发消息

request.setAttribute("msg",msg);

request.getRequestDispatcher("/info.jsp").forward(request,response);

}catch(FileUploadException e){

e.printStackTrace();

}

}public staticDiskFileItemFactory gteDiskFileItemFactory(File file){//1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小

DiskFileItemFactory factory = newDiskFileItemFactory();//通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中;

factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M

factory.setRepository(file);returnfactory;

}public staticServletFileUpload getServletFileUpload(DiskFileItemFactory factory){//2、获取ServletFileUpload

ServletFileUpload upload = newServletFileUpload(factory);/*//监听文件上传进度

upload.setProgressListener(new ProgressListener() {

@Override

public void update(long pBytesRead, long lpContentLenght, int i) {

//pBytesRead:已读取到的文件大小

//pContentLenght:文件大小

System.out.println("总大小:"+lpContentLenght+"已上传:"+pBytesRead);

}

});

//处理乱码问题

upload.setHeaderEncoding("UTF-8");

//设置单个文件的最大值

upload.setFileSizeMax(1024 * 1024 * 10);

//设置总共能够上传文件的大小

//1024 = 1kb * 1024 = 1M * 10 = 10M

upload.setSizeMax(1024 * 1024 * 10);*/

return upload;

}public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadpath) throwsIOException, FileUploadException { String msg= "";//3、处理上传文件//把前端的请求解析,封装成一个FileItem对象 List fileItems =upload.parseRequest(request);for(FileItem fileItem : fileItems) {if (fileItem.isFormField()){ //判断是普通表单还是带文件的表单//getFieldName指的是前端表单控件的name String name =fileItem.getFieldName(); String value= fileItem.getString("UTF-8");//处理乱码 System.out.println(name+":"+value); }else {//判断它是带文件的表单//======================处理文件=======================// //拿到文件的名字 String uploadFileName =fileItem.getName(); System.out.println("上传的文件名:"+uploadFileName);if (uploadFileName.trim().equals("") || uploadFileName == null){continue; }//获得上传的文件名,例如/img/girl/ooa.jpg,只需要ooa,其前面的后面的都不需要 String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);//获得文件的后缀名 String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);/** 如果后缀名 fileExtName 不是我们需要的 *就直接return,不处理,告诉用户类型不对 **/System.out.println("文件信息【文件名:"+fileName+"文件类型:"+fileExtName+"】");//可以使用UUID(唯一通用识别码)来保证文件名的统一 String uuidFileName =UUID.randomUUID().toString();//=======================传输文件=========================// //获得文件上传的流 InputStream inputStream =fileItem.getInputStream();//创建一个文件输出流 FileOutputStream fos = new FileOutputStream(uploadpath + "/" + uuidFileName +"."+fileExtName);//创建一个缓冲区 byte[] buffer = new byte[1024 * 1024];//判断是否读取完毕 int len = 0;//如果大于0,说明还存在数据 while ((len=inputStream.read(buffer))>0){ fos.write(buffer,0,len); }//关闭流 fos.close(); inputStream.close(); msg= "文件上传成功!"; fileItem.delete();//上传成功,清除临时文件 } }returnmsg; } }

//package com.cong.servlet;
//
//import org.apache.commons.fileupload.FileItem;
//import org.apache.commons.fileupload.FileUploadException;
//import org.apache.commons.fileupload.disk.DiskFileItemFactory;
//import org.apache.commons.fileupload.servlet.ServletFileUpload;
//
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.File;
//import java.io.FileOutputStream;
//import java.io.IOException;
//import java.io.InputStream;
//import java.util.List;
//import java.util.UUID;
//
//public class FileServlet extends javax.servlet.http.HttpServlet{
//    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//
//        //判断上传的文件是普通表单还是带文件的表单
//        if(!ServletFileUpload.isMultipartContent(request)){
//            return;//终止方法运行,说明这是一个普通的表单,直接返回
//        }
//
//        //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件;
//        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
//        File uploadFile = new File(uploadPath);
//        if(!uploadFile.exists()){
//            uploadFile.mkdir();//创建这个目录
//        }
//
//        //缓存,临时文件
//        //临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
//        String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
//        File file = new File(tmpPath);
//        if(!file.exists()){
//            file.mkdir();//创建这个临时文件目录
//        }
//
//        //处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream() ,原生态的文件上传流获取,十分麻烦
//        //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload, 它需要依赖于commons-io组件
//
//        //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小的限制的:
//        DiskFileItemFactory factory = new DiskFileItemFactory();
//        /*
//        //通过这个工厂设置一个缓冲区,当上传的我呢见大于这个缓冲区的时候,将他放到临时文件中;
//        factory.setSizeThreshold(1024*1024);//缓冲区大小为1M
//        factory.setRepository(file);//临时目录的保存目录,需要一个File
//        */
//
//        //2.获取ServletFileUpload
//        ServletFileUpload upload = new ServletFileUpload(factory);
//
//        //3.处理上传的文件
//        try {
//            String msg = uploadParseRequest(upload,request,uploadPath);
//            //servlet请求转发消息
//            request.setAttribute("msg", msg);
//            request.getRequestDispatcher("/info.jsp").forward(request,response);
//        }catch (FileUploadException e){
//            e.printStackTrace();
//        }
//
//
////3.处理上传的文件//把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象中获取try {List<FileItem> fileItems = upload.parseRequest(request);//fileItem每一个表单对象for (FileItem fileItem : fileItems) {//判断上传的文件是普通的表单还是带文件的表单if (fileItem.isFormField()) {//getFileName指的是前端表单控件的name;String name = fileItem.getFieldName();String value = fileItem.getString("UTF-8");//处理乱码System.out.println(name + ":" + value);}else{//文件//=================处理文件====================////拿到文件的名字String uploadFileName = fileItem.getName();//可能出现文件名不合法的情况if(uploadFileName.trim().equals("") || uploadFileName==null){continue;}//获得上传的文件名 /images/girl/paojie.pngString fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);//获得文件的后缀名String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);//网络传输中的东西,都需要序列化//POJO,实体类,如果想要早多个电视上运行,     传输====》需要把对象都序列化了//implements Serializable : 标记接口     jvm----》本地方法栈    native----》C++//可以使用UUID(唯一识别的通用码),保证文件名唯一;//UUID.randomUUID(),随机生一个唯一识别的通用码String uuidPath = UUID.randomUUID().toString();//=================存放地址====================////存到哪? uploadPath//文件真实存在的路径realPathString realPath = uploadPath+"/"+uuidPath;//给每个文件创建一个对应的文件夹File realPathFile = new File(realPath);if(!realPathFile.exists()){realPathFile.mkdir();}//=================文件传输====================////获得文件上传的流InputStream inputStream = fileItem.getInputStream();//创建一个文件输出流//realPath = 真实的文件夹//差了一个文件;加上输出文件的名字+“/”+uuidFileNameFileOutputStream fos = new FileOutputStream(realPath+"/"+fileName);//创建一个缓冲区byte[] buffer = new byte[1024*1024];//判断是否读取完毕int len = 0;//如果大于0说明还存在数据;while((len = inputStream.read(buffer))>0){fos.write(buffer, 0, len);}//关闭流fos.close();inputStream.close();msg = "文件上传成功";fileItem.delete();//上传成功,清除临时文件}return msg;}
//
//
//    }
//
//    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//
//    }
//    public static DiskFileItemFactory gteDiskFileItemFactory(File file){
1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小
//
//        DiskFileItemFactory factory = new DiskFileItemFactory();
//
通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中;
//
//        factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M
//
//        factory.setRepository(file);
//
//        return factory;
//
//    }
//
//    public static String getServletFileUpload(DiskFileItemFactory factory){
2、获取ServletFileUpload
//
//        ServletFileUpload upload = new ServletFileUpload(factory);
//
///*//监听文件上传进度
//
//upload.setProgressListener(new ProgressListener() {
//@Override
//
//public void update(long pBytesRead, long lpContentLenght, int i) {
pBytesRead:已读取到的文件大小
//
pContentLenght:文件大小
//
//System.out.println("总大小:"+lpContentLenght+"已上传:"+pBytesRead);
//
//}
//
//});
//
处理乱码问题
//
//upload.setHeaderEncoding("UTF-8");
//
设置单个文件的最大值
//
//upload.setFileSizeMax(1024 * 1024 * 10);
//
设置总共能够上传文件的大小
//
1024 = 1kb * 1024 = 1M * 10 = 10M
//
//upload.setSizeMax(1024 * 1024 * 10);
//
//return upload;
//
//}*/
//
//        public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadpath) throws IOException, FileUploadException {
//            String msg = "";
//
3、处理上传文件
//
把前端的请求解析,封装成一个FileItem对象
//
//            List fileItems = upload.parseRequest(request);
//
//            for (FileItem fileItem : fileItems) {
//                if (fileItem.isFormField()){ //判断是普通表单还是带文件的表单
//
getFieldName指的是前端表单控件的name
//
//                    String name = fileItem.getFieldName();
//
//                    String value = fileItem.getString("UTF-8");//处理乱码
//
//                    System.out.println(name+":"+value);
//
//                }else {//判断它是带文件的表单
//
======================处理文件=======================//
//
拿到文件的名字
//
//                    String uploadFileName = fileItem.getName();
//
//                    System.out.println("上传的文件名:"+uploadFileName);
//
//                    if (uploadFileName.trim().equals("") || uploadFileName == null){
//                        continue;
//
//                    }
//
获得上传的文件名,例如/img/girl/ooa.jpg,只需要ooa,其前面的后面的都不需要
//
//                    String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
//
获得文件的后缀名
//
//                    String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
//
//                    /*
//
//                     * 如果后缀名 fileExtName 不是我们需要的
//
//                     *就直接return,不处理,告诉用户类型不对
//
//                     * */
//
//                    System.out.println("文件信息【文件名:"+fileName+"文件类型:"+fileExtName+"】");
//
可以使用UUID(唯一通用识别码)来保证文件名的统一
//
//                    String uuidFileName = UUID.randomUUID().toString();
//
=======================传输文件=========================//
//
获得文件上传的流
//
//                    InputStream inputStream = fileItem.getInputStream();
//
创建一个文件输出流
//
//                    FileOutputStream fos = new FileOutputStream(uploadpath + "/" + uuidFileName +"."+ fileExtName);
//
创建一个缓冲区
//
//                    byte[] buffer = new byte[1024 * 1024];
//
判断是否读取完毕
//
//                    int len = 0;
//
如果大于0,说明还存在数据
//
//                    while ((len=inputStream.read(buffer))>0){
//                        fos.write(buffer,0,len);
//
//                    }
//
关闭流
//
//                    fos.close();
//
//                    inputStream.close();
//
//                    msg = "文件上传成功!";
//
//                    fileItem.delete();//上传成功,清除临时文件
//
//                }
//
//            }
//
//            return msg;
//
//        }
//
//    }
//}
package com.cong.servlet;import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.*;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;@WebServlet("/upload") // 定义 Servlet 映射路径
public class FileServlet extends HttpServlet {private static final long serialVersionUID = 1L;// 设置最大文件大小为 10MBprivate static final int MAX_FILE_SIZE = 10 * 1024 * 1024;// 设置内存缓冲区大小为 1MBprivate static final int MEMORY_THRESHOLD = 1 * 1024 * 1024;// 上传文件存储目录private static final String UPLOAD_DIRECTORY = "WEB-INF/upload";// 临时文件存储目录private static final String TEMP_DIRECTORY = "WEB-INF/temp";@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 检查请求是否为多部分内容if (!ServletFileUpload.isMultipartContent(request)) {// 如果不是,设置错误信息并转发到 info.jsprequest.setAttribute("message", "错误:表单必须包含 enctype=multipart/form-data");request.getRequestDispatcher("/info.jsp").forward(request, response);return;}// 配置上传参数DiskFileItemFactory factory = getDiskFileItemFactory(request);ServletFileUpload upload = getServletFileUpload(factory);// 设置整体请求的大小限制upload.setSizeMax(MAX_FILE_SIZE);// 确保上传目录存在String uploadPath = getServletContext().getRealPath("/") + File.separator + UPLOAD_DIRECTORY;File uploadDir = new File(uploadPath);if (!uploadDir.exists()) {uploadDir.mkdirs();}String message = "";try {// 解析请求的内容以提取文件数据List<FileItem> formItems = upload.parseRequest(request);if (formItems != null && !formItems.isEmpty()) {// 遍历表单字段for (FileItem item : formItems) {// 处理非表单字段if (item.isFormField()) {String fieldName = item.getFieldName();String fieldValue = item.getString("UTF-8");System.out.println("普通表单字段:" + fieldName + " = " + fieldValue);} else {// 处理文件字段String fileName = Paths.get(item.getName()).getFileName().toString();if (fileName == null || fileName.trim().isEmpty()) {message = "未选择文件上传";continue;}// 检查文件大小if (item.getSize() > MAX_FILE_SIZE) {message = "文件大小超过限制(10MB)";continue;}// 检查文件类型(根据需要,可以添加更多类型)String fileExt = getFileExtension(fileName);if (!isAllowedFileType(fileExt)) {message = "不支持的文件类型:" + fileExt;continue;}// 生成唯一的文件名,防止重名String newFileName = UUID.randomUUID().toString() + "_" + fileName;// 保存文件到指定路径File storeFile = new File(uploadDir, newFileName);try (InputStream inputStream = item.getInputStream();FileOutputStream outputStream = new FileOutputStream(storeFile)) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}message = "文件上传成功:" + newFileName;System.out.println(message);}}}} catch (FileUploadException e) {message = "错误信息: " + e.getMessage();e.printStackTrace();}// 将消息存储在请求范围内request.setAttribute("message", message);// 转发到 info.jsprequest.getRequestDispatcher("/info.jsp").forward(request, response);}/*** 配置 DiskFileItemFactory*/private DiskFileItemFactory getDiskFileItemFactory(HttpServletRequest request) {// 配置工厂参数DiskFileItemFactory factory = new DiskFileItemFactory();// 设置内存缓冲区大小factory.setSizeThreshold(MEMORY_THRESHOLD);// 设置临时文件存储位置String tempPath = getServletContext().getRealPath("/") + File.separator + TEMP_DIRECTORY;File tempDir = new File(tempPath);if (!tempDir.exists()) {tempDir.mkdirs();}factory.setRepository(tempDir);return factory;}/*** 配置 ServletFileUpload*/private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {return new ServletFileUpload(factory);}/*** 获取文件扩展名*/private String getFileExtension(String fileName) {if (fileName == null || fileName.trim().isEmpty()) {return "";}int dotIndex = fileName.lastIndexOf(".");return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1).toLowerCase();}/*** 检查是否为允许的文件类型*/private boolean isAllowedFileType(String fileExt) {// 定义允许的文件类型(根据需求添加)String[] allowedTypes = {"jpg", "jpeg", "png", "gif", "pdf", "doc", "docx"};for (String type : allowedTypes) {if (type.equalsIgnoreCase(fileExt)) {return true;}}return false;}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 直接跳转到上传页面(根据实际情况调整)response.sendRedirect("upload.jsp");}
}

相关文章:

java文件上传

导入jar包&#xff0c;或者maven <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>…...

MySQL 数据库经验总结

一、数据库操作 1. 创建数据库 CREATE DATABASE database_name;例如&#xff0c;创建一个名为 my_database 的数据库&#xff1a; CREATE DATABASE my_database;2. 选择数据库 USE database_name;要使用刚才创建的 my_database 数据库&#xff1a; USE my_database;3. 删除…...

Python环境安装及PIP安装(Mac OS版)

官网 https://www.python.org/downloads/ 安装python python-3.12.1-macos11.pkg下载后&#xff0c;安装一直下一步即可 验证是否安装成功&#xff0c;执行python3命令和pip3命令 配置环境变量 获取python3安装位置并配置在.bash_profile #查看python路径 which python3#…...

2024自动驾驶(多模态)大模型综述:从DriveGPT4、DriveMLM到DriveLM、DriveVLM

前言 由于今年以来&#xff0c;一直在不断深挖具身智能机器人相关&#xff0c;而自动驾驶其实和机器人有着无比密切的联系&#xff0c;甚至可以认为&#xff0c;汽车就是一个带着4个轮子的机器人 加之个人认为&#xff0c;目前大模型落地潜力最大的两个方向&#xff0c;一个是…...

晨控CK-GW08-EC与汇川AC801系列PLC的EtherCAT通讯连接说明手册

晨控CK-GW08-EC与汇川AC801系列PLC的EtherCAT通讯连接说明手册 晨控CK-GW08-EC是一款支持标准工业通讯协议EtherCAT的网关控制器,方便用户集成到PLC等控制系统中。系统还集成了8路读写接口&#xff0c;用户可通过通信接口使用EtherCAT协议对8路读写接口所连接的读卡器进行相对…...

向上or向下调整建堆 的时间复杂度的本质区别的讲解

知识点&#xff1a;&#xff08;N代表节点数&#xff0c;h代表高度&#xff09; 1&#xff1a;高度为h的满二叉树节点个数N为 2^&#xff08;h&#xff09;-1 即N 2^&#xff08;h&#xff09;-1 2&#xff1a;所以h log&#xff08;N1&#xff09; 一&#xff1a;向上…...

阿一网络安全实战演练之利用 REST URL 中的服务器端参数污染

所需知识 要解决这个实验室问题&#xff0c;您需要了解以下内容&#xff1a; 如何确定用户输入是否包含在服务器端的 URL 路径或查询字符串中。如何使用路径遍历序列尝试更改服务器端请求。如何查找 API 文档。 这些内容在我们的 API 测试学院主题中有涵盖。 进入实验室 研…...

[游戏开发] LuaTable转string存读二进制文件

UE5和Unity通用此方案&#xff0c;只不过读写文件的接口略有不同&#xff0c;lua代码的处理是相同的。 下面两个方法是 LuaTable和字符串互相转换的代码 function XUtils.luaTableToString(tab, sp)sp sp or ""local s ""for k,v in pairs(tab) doif t…...

光伏业务管理系统的一些妙用功能

现在信息化流程化基本上每个行业都必须要有的了&#xff0c;光伏业务管理系统软件是一种专门用于光伏产业运营和管理的综合性系统&#xff0c;它结合了信息技术、数据分析、项目管理、客户管理等多个领域的知识&#xff0c;为光伏企业提供了一个全面、高效、智能的管理平台&…...

Java面试八股之请简述消息队列的发布订阅模式

请简述消息队列的发布订阅模式 发布订阅&#xff08;Publish-Subscribe&#xff0c;简称 Pub/Sub&#xff09;模型是一种消息传递模式&#xff0c;它在组件之间提供了高度的解耦和灵活性。这种模式广泛应用于分布式系统、事件驱动架构以及消息队列系统中。下面是发布订阅模型的…...

七、2 ADC数模转换器有关函数介绍(Keil5)

函数介绍 &#xff08;1&#xff09;ADCCLK的配置函数&#xff08;在rcc.h中&#xff09; &#xff08;2&#xff09;ADC的库函数&#xff08;在adc.h中&#xff09;...

了解载波侦听多路访问CSMA(上)

1.CSMA的思想 CSMA的全称是Carrier Sense Multiple Access&#xff0c;在笔者的理解中&#xff0c;其更趋向于一种理论研究的随机接入协议&#xff0c;或者说&#xff0c;基于其思想诞生了比如CSMA/CD与CSMA/CA这样的具体协议。CSMA可以分成以下三种&#xff1a; 1-persistent…...

开启教育新征程:“集师” 知识付费平台搭建

在教育培训行业竞争日益激烈的今天&#xff0c;如何脱颖而出&#xff0c;实现知识的最大价值&#xff1f;答案就在 “集师” 知识付费平台搭建&#xff01; “集师” 为您打造专属的知识付费平台&#xff0c;提供一站式解决方案。无论您是专注于学科教育、艺术培训还是职业技能…...

Vue3 + Electron 创建新的子窗口 且子窗口唯一

main.js const { app, BrowserWindow, ipcMain } require(electron) ...ipcMain.on(window-create, () > {createChildWindow() })let childWindow nullconst createChildWindow () > {// 如果窗口存在 先销毁if (childWindow) {childWindow.destroy()childWindow n…...

海康VisionMaster使用学习笔记2-相机取图及参数设置

相机取图及参数设置 1. 关联相机-相机管理界面 除了以上两类外,第三方相机都可以通过全局相机进行连接 2. 相机参数设置 相机连接 跨网段IP,枚举 图像缓存数量 实时取流,断线重连 只有支持组播的相机才可以实时取流 触发设置 触发源 LINE0 可以保护电路 LINE2 可配置输入输出…...

【网络】【Linux】Linux内核中连接的组织形式与全连接队列

Linux内核中连接的组织形式与全连接队列 文章目录 1.前言2.Linux内核中连接的组织形式2.1套接字和文件描述符2.2创建连接 & 获取连接 3.全连接队列3.1为什么有全连接队列&#xff1f;3.2全连接队列的长度 1.前言 TCP是面向连接的&#xff0c;TCP的各种可靠性机制实际都不…...

记录一次 npm ERR! cb() never called! 解决过程

gitlab cicd过程&#xff0c;使用docker部署Vue3前端项目&#xff0c;报错如下&#xff1a; 针对 npm ERR! cb() never called! 这个报错&#xff0c;网上有很多解决方案&#xff0c;大都是清空缓存&#xff0c;重新运行npm 之类的。笔者全都试过&#xff0c;无法解决问题。笔者…...

WEB渗透免杀篇-加载器免杀

SSI加载 https://github.com/DimopoulosElias/SimpleShellcodeInjector生成payload(c) msfvenom -p windows/meterpreter/reverse_tcp lhost192.168.0.108 lport12138 -f c -o shellcode.c执行 cat shellcode.c |grep -v unsigned|sed "s/\"\\\x//g"|sed &quo…...

什么是反人性设计?

目录 一、什么是人性&#xff1f; 二、什么是反人性设计&#xff1f; 三、有哪些反人性设计&#xff1f; 一、什么是人性&#xff1f; 人性&#xff0c;通常指的是人类共有的基本特质和行为倾向&#xff0c;它涵盖了一系列心理、情感和社会属性。人性可以从多个角度来理解&a…...

如何进行长截图的两种方法

前言 本文主要讲2种截图方式&#xff0c;分别是谷歌和QQ。 谷歌分为Web端 和 移动端&#xff0c;选一种即可。 第一种&#xff1a;谷歌浏览器控制台自带的 1.先把控制台语言更改为中文&#xff0c;方便查看 ①.按F12&#xff0c;点击设置面板 ②.修改语言为中文并关闭 ③.点击…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...