APICloud(四):图片上传-Java版

2023-11-18

这一篇讲“将选择的图片上传到指定的服务器”。

说实话,这个功能写了好久,一会儿json拼的有问题访问不到后台,一会儿后台又说form表单的enctype不是multipart/form-data类型,各种乱七八糟的问题折腾了一下午都没好,第二天再弄的时候,竟然莫名其妙的好了,而且后来再也没出过问题。真是匪夷所思啊!

好啦,废话说到这里,言归正传。

这里以发布公告为例:输入公告内容,上传需要的图片(也可以不上传),点击“保存”按钮进行数据提交。其中内容能够和图片必须有一项不为空,“保存”按钮触发事件savaAnnounce()。

一、提交数据的代码如下:

/**
 *该方法用来保存公告
 * @param obj:A标签
 *  **/
function savaAnnounce(obj){
	//判断保存是灰色的还是绿色的,若是灰色的不能保存
	var opacity = $(obj).css("opacity");
	//当前按钮处于置灰状态,不能操作
	if((opacity+"")=="0.5") return false;
	
	//进行进度条提示	
	api.showProgress({
    	title: '数据提交中',
    	modal: false
	});
	
	//1、获取公告内容
	var announceContent = jQuery.trim($("#announceContent").val());//去除左右的空格
	var contentLen = announceContent.length;
	if(contentLen>0){//说明有填写内容,那么校验是否有特殊词汇,若是没有内容不校验		
		//判断是否有敏感词汇
		if(checkStr2(announceContent) || checkStr2(announceContent)){//两个当中有一个有特殊字符
			showErrorInfoBySys("内容不允许有特殊字符","1");
			return false;
		}
	}else{//说明没有数据
		announceContent = "";
	}
	
	//2、获取图片数量
	var picLen = $("#picList").children().length;
	
	//alert(contentLen+"\n"+picLen);
	//3、若是内容和图片数量都为0,说明什么都没有填写,那么不能提交数据
	if(contentLen<=0 && picLen<=0){
		showErrorInfoBySys("请输入内容或上传图片","1");
		return false;
	}
	
	//4、处理图片路径信息
	var fileList = "";
	if(picLen>0){
		$("#picList").children().each(function(i){		
			fileList+=",\"file"+(i+1)+"\":\""+this.children[0].src+"\"";//只显示文件名称
		});
		//截取掉最开始的逗号
		if(fileList.length>1){
			fileList = fileList.substring(1);
		}	
	}	
	fileList = eval('('+("{"+fileList+"}")+')');
	
	//4、提交数据	
	api.ajax({
	    url:$api.getStorage("url"),
	    method:'post',
	    dataType:'text',
	    data:{
	    	values:{
        		'announceContent':announceContent,
	        	'user_id':$api.getStorage("u_id"),
	        	'user_name':$api.getStorage("u_name"),
	        	'time':new Date().getTime()
	    	},	    	
	    	files:fileList
	    }
	},function(ret, err){
		api.hideProgress();//隐藏进度提示框		
	    if (ret) {
		     //跳转到公告列表界面:
		     api.openWin({
		          name: 'my_notice',
		          url: 'mynotice.html',
		          pageParam:{
		                'user_id':$api.getStorage("u_id")
		            },
		            progress:{
		            	type:"default",
		            	title:"玩命加载中..."
		            }
	            });
	    } else {
	        api.alert(JSON.stringify(err));
	    }    			    
	});	
}

/**
 *该方法用来显示错误信息-调用系统定时方法
 * @param flag:1-隐藏进度提示框 非1:不隐藏
 * @param msg:错误信息
 * **/
function showErrorInfoBySys(msg,flag){
	if((flag+"")=="1"){
		api.hideProgress();//隐藏进度提示框
	}
	//显示错误信息
	api.toast({
	    msg: msg,
	    duration: time,
	    location: 'bottom'
	});   		
}

/**该方法用来判断字符串中是否存在特殊字符-只包括SQL常用关键字
/*true:说明有特殊字符
/*false:说明没有特殊字符
 */
function checkStr2(str){
	var myReg = new RegExp("(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)");
	if(myReg.test(str)) return true; 
	return false; 
}

 二、后台进行文件上传

servlet

String retuStr="提交失败!";		
Object result = new com.wjl.dataengine.UploadFile().upload(request, response);
if(result instanceof SUser ){//如果是user的子类,说明添加成功
	//往数据库中添加日志
	addLog((SUser)result,"添加公告");
	retuStr="提交成功!";
}else{
	retuStr = result.toString();//否则就是错误信息
}
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Cache-Control", "no-store");
response.setDateHeader("Expires", 0);
System.out.println("retuStr:"+retuStr);
response.getWriter().write(retuStr);
response.getWriter().flush();
response.getWriter().close();

文件上传

/**
 * 该方法用来上传文件
 * @param request:request请求
 * @return Object:若是suer对象说明添加成功,否则返回错误信息
 * **/
public Object upload(HttpServletRequest request,final HttpServletResponse response){
	Object retuStr="提交失败!";	
//1、判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(request)){//不是上传表单的数据
    //按照传统方式获取数据
	String announceContent = request.getParameter("announceContent");//公告内容
	String user_id = request.getParameter("user_id");//发布人序号
	String user_name = request.getParameter("user_name");//发布人
	System.out.println("内容:\n"+announceContent);
	/*
	try{
		String announceContent2 =URLDecoder.decode(announceContent,"utf-8");
		announceContent = announceContent2;
		System.out.println("转码之后的公告内容:"+announceContent);
	}catch(Exception e){
		e.printStackTrace();
	}
	*/
	if(announceContent==null || announceContent.trim().length()<=0){ 
		return "内容不能为空!";
	}else{
		result= new com.wjl.ServicesImpl().addAnnounce(announceContent,"",user_id,user_name);	
		if(result.trim().length()<=0){//说明添加成功了
			SUser user = new SUser();
			user.setS_user_id(Integer.parseInt(user_id));
			user.setS_username(user_name);
			return user;
		}else{//说明添加失败
			return retuStr;
		}
	}
}
//2、处理上传了文件的情况
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String savePath = getSavePath();
if(savePath.length()<=0){
	savePath = request.getRealPath("/")+"upload";
}
String year = com.wjl.Time.year().toString();//年份
String month = com.wjl.util.Time.month().toString();//月份
String day = com.wjl.util.Time.date().toString();//日
String tempPathForFile = year+File.separator+month+File.separator+day;
String filePath = "";
//上传时生成的临时文件保存目录
String tempPath = getTempPath();
if(tempPath.length()<=0){
	tempPath = request.getRealPath("/")+"temp";
}
File tmpFile = new File(tempPath);
if (!tmpFile.exists()) {
    //创建临时目录
    tmpFile.mkdir();
}                
try{
    //使用Apache文件上传组件处理文件上传步骤:
    //1、创建一个DiskFileItemFactory工厂
    DiskFileItemFactory factory = new DiskFileItemFactory();
    //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
    factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
    //设置上传时生成的临时文件的保存目录
    factory.setRepository(tmpFile);
    
    //2、创建一个文件上传解析器
    ServletFileUpload upload = new ServletFileUpload(factory);
    //监听文件上传进度
    upload.setProgressListener(new ProgressListener(){
        public void update(long pBytesRead, long pContentLength, int arg2) {
            try {
            	float f = pBytesRead/pContentLength;
            	response.getWriter().write(f+"");
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
    });
    
     //解决上传文件名的中文乱码
    upload.setHeaderEncoding("UTF-8"); 
    
    
    //设置上传单个文件的大小的最大值,目前是设置为10*1024*1024字节,也就是10MB
    upload.setFileSizeMax(getFileBufferForSingle());
    
    //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为20MB
    upload.setSizeMax(getFileBufferFotTotal());
    //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
    List<FileItem> list = upload.parseRequest(request);
    
    //获取公告信息
    String announceContent = "";//公告内容
	String user_id = "";//发布人序号
	String user_name = "";//发布人
    StringBuffer imgInfo = new StringBuffer();//图片信息
    for(FileItem item : list){
        //如果fileitem中封装的是普通输入项的数据
        if(item.isFormField()){
            String name = item.getFieldName().trim();
            //解决普通输入项的数据的中文乱码问题
            String value = item.getString("UTF-8");
            if(value==null || value.trim().length()<=0)value="";
            else value = value.trim();
            //value = new String(value.getBytes("iso8859-1"),"UTF-8");
           //System.out.println("基础信息:\n"+name + "=" + value);
           //System.out.println("传过来的参数值:"+FieldType.getFileType(name));
           switch(FieldType.getFileType(name)){
           case ANNOUNCECONTENT:announceContent = value;break;
           case USER_ID:user_id = value;break;
           case USER_NAME:user_name = value;break;
           case TIME:break;
           default:break;
           }
        }else{//如果fileitem中封装的是上传文件
            //得到上传的文件名称,
            String filename = item.getName();
            if(filename==null || filename.trim().equals("")){
                continue;
            }
            //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
            //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
            filename = filename.substring(filename.lastIndexOf("\\")+1);
            //得到上传文件的扩展名
            //String fileExtName = filename.substring(filename.lastIndexOf(".")+1);
            //如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
            //System.out.println("上传的文件名称是:"+filename+"\n上传的文件的扩展名是:"+fileExtName);
            //获取item中的上传文件的输入流
            InputStream in = item.getInputStream();
            //得到文件保存的名称
            String saveFilename = makeFileName(filename);
            //得到文件的保存目录
            String realSavePath = makePath(saveFilename, tempPathForFile);
            //拼接图片路径用来保存到数据库
            imgInfo.append(","+File.separator+"bfp"+File.separator+realSavePath+File.separator+saveFilename);
            realSavePath = savePath+File.separator+realSavePath;
            System.out.println("文件目录:"+realSavePath);
            //File既可以代表文件也可以代表目录
   	     	File file = new File(realSavePath);
   	     	//如果目录不存在
   	     	if(!file.exists()){
   	     		//创建目录
   	     		file.mkdirs();
   	     	}
            //创建一个文件输出流
            FileOutputStream out = new FileOutputStream(realSavePath+File.separator+saveFilename);
            //创建一个缓冲区
            byte buffer[] = new byte[1024];
            //判断输入流中的数据是否已经读完的标识
            int len = 0;
            //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
            while((len=in.read(buffer))>0){
                //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
                out.write(buffer, 0, len);
            }
            //关闭输入流
            in.close();
            //关闭输出流
            out.close();
            //删除处理文件上传时生成的临时文件
          item.delete();
          //retuStr = "文件上传成功!";
        }
    }
    String img = "";
    if(imgInfo.length()>1){
    	img = imgInfo.substring(1);
    }else{img="''";}
    
    //往数据库中添加内容
    String result="";
   result= new com.wjl.ServicesImpl().addAnnounce(announceContent,img,user_id,user_name);
	if(result.trim().length()<=0){//说明添加成功了
		SUser user = new SUser();
		user.setS_user_id(Integer.parseInt(user_id));
		user.setS_username(user_name);
		return user;
	}else{//说明添加失败
		return retuStr;
	}
}catch (FileUploadBase.FileSizeLimitExceededException e) {
    e.printStackTrace();
    retuStr="单个文件超出最大值!!!";
}catch (FileUploadBase.SizeLimitExceededException e) {
    e.printStackTrace();
    retuStr="上传文件的总的大小超出限制的最大值!!!";
}catch (Exception e) {
	retuStr= "文件上传失败!";
        e.printStackTrace();
    }
    return retuStr;
 }

 上传代码中用到的一些工具类

//1、上传的各个参数所在类
public enum FieldType {
	//规定表单字段
	ANNOUNCECONTENT,USER_ID,USER_NAME,TIME;  
      
    //提供方法用来获取文件类型  
    public static FieldType getFileType(String fileType){  
        return valueOf(fileType.toUpperCase());  
    }  
}

//2、时间操作类:
public class Time {
	public static GregorianCalendar ggcalendar=new GregorianCalendar(Locale.CHINA);
/**
	 * 返回当前的年
	 * @return
	 */
	public static Integer year(){
		return ggcalendar.get(Calendar.YEAR);
	}
	/**
	 * 返回当前月份
	 * @return
	 */
	public static  Integer month(){
		return ggcalendar.get(Calendar.MONTH)+1;
	}
/**
	 * 返回当前是几号
	 * @return
	 */
	public static  Integer date(){
		return ggcalendar.get(Calendar.DATE);
	}
}

//3、文件操作代码
/**
 * @Method: makeFileName
 * @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
 * @param filename 文件的原始名称
 * @return uuid+"_"+文件的原始名称
 */ 
 private String makeFileName(String filename){  //2.jpg
     //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
     return UUID.randomUUID().toString() + "_" + filename;
 }
 
 /**
  * 为防止一个目录下面出现太多文件,要使用hash算法打散存储
 * @Method: makePath
 * @Description: 
 * @param filename 文件名,要根据文件名生成存储目录
 * @param savePath 文件存储路径
 * @return 新的存储目录
 */ 
 private String makePath(String filename,String savePath){
     //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
     int hashcode = filename.hashCode();
     int dir1 = hashcode&0xf;  //0--15
     int dir2 = (hashcode&0xf0)>>4;  //0-15
     //构造新的保存目录
     String dir = savePath + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5
     return dir;
 }
 
/**
 * 该方法用来获取允许上传的文件总大小
 * **/
public long getFileBufferFotTotal(){
	long buffer = 200*1024*1024;//文件上传允许最大为200M
	String fileSize = com.wjl.util.WebAppConfig.app("businessFileSizeForTotal");
	if(fileSize!=null){//说明有设置值
		fileSize = fileSize.trim();
		//有设置值且是数字
		if(fileSize.length()>0 && com.wjl.util.Utils.isNumeric(fileSize)){
			buffer = Integer.parseInt(fileSize)*1024*1024;
		}
	}
	return buffer;
}

/**
 * 该方法用来获取允许上传的单个文件大小
 * @return long:配置文件中配置的数据*1024*1024,也就是总共多少M
 * **/
public long getFileBufferForSingle(){
	long buffer = 10*1024*1024;//文件上传允许最大为200M
	String fileSize = com.wjl.util.WebAppConfig.app("businessFileSize");
	if(fileSize!=null){//说明有设置值
		fileSize = fileSize.trim();
		//有设置值且是数字
		if(fileSize.length()>0 && com.wjl.util.Utils.isNumeric(fileSize)){
			buffer = Integer.parseInt(fileSize)*1024*1024;
		}
	}
	return buffer;
}

/**
 * 该方法用来获取文件保存的路径
 * */
public String getSavePath(){
	String savePath = com.wjl.util.WebAppConfig.app("businessFilePath");
	if(savePath!=null && savePath.trim().length()>0){
		savePath = savePath.trim();
	}else{
		savePath = "";
	}
	return savePath;
}

/**
 * 该方法用来获取文件临时保存的路径
 * */
public String getTempPath(){
	String savePath = com.wjl.util.WebAppConfig.app("businessFileTempPath");
	if(savePath!=null && savePath.trim().length()>0){
		savePath = savePath.trim();
	}else{
		savePath = "";
	}
	return savePath;
}

//4、读取配置文件的类:
public final class WebAppConfig { 
/** 
     * 私有构造方法,不能创建对象 
     */ 
    private WebAppConfig() { } 
	/***
	 * 
	 * @param key:properties文件中各个选项的name值
	 * @return String:与name值对应的value值
	 */
	public static String app(String key){
		String value=null;
        if(key!=null && key.trim().length()>0){
        	Properties prop = new Properties(); 
            //读取指定的文件
        	InputStream in = WebAppConfig.class.getResourceAsStream("/webApp.properties"); 
            try { 
                prop.load(in); 
                value = prop.getProperty(key).trim(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            }
        }
        return value;
    }
}

 

 

 

 

 

 

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

APICloud(四):图片上传-Java版 的相关文章

  • Switch / Xbox / PS / PSV / PSP 游戏指南

    1 Switch Xbox PS PSV PSP 对比分析 table 1 PSV2000 1000 比较分析 PSV2000 相对 PSV1000 具体变更点 薄了20 轻了15 屏幕改为液晶屏 PS键 开始键和选择键变成球形更方便按 内
  • 2,一个人体姿态识别的项目实现

    学习opencv的例子 1 认识 2 start 直接干货 例子1 例子2 例子3 例子4 例子5 固定阈值 自适应阈值 文档说明 参考链接 http codec wang opencv start 02 basic element ima
  • git仓库创建及上传

    如何创建一个git仓库并上传代码 1 在此之前我们需要安装git和注册gitee账号 1 打开git官网下载安装程序 然后按照指令进行安装即可 2 搜索gitee进行注册和绑定邮箱即可 上传代码时需要登录gitee账号 安装成功之后告诉本地
  • Android apk 反编译解析

    学习android开发 有必要对android的反编译有所了解 当然学习android反编译并不是为了破解别人的软件 完全是一种学习的方法 了解别人写程序的思想是一件很有趣的事情 工具下载地址 http code google com p
  • androidstudio开发!花三分钟看完这篇文章你就懂了!技术详细介绍

    阿里面试 自我介绍 首先要介绍自己的项目经验和个人的擅长点 因为面试官主要考察你的表达能力和语言精简能力 简历的编写其实这里可能需要注意几点 1 标题的直接按照姓名 几年工作经验 应聘岗位格式来填写 例如 黄铭 四年工作经验 Android
  • STP与RSTP区别

    STP 不能快速迁移 即使是在点对点链路或边缘端口 边缘端口指的是该端口直接与用户终端相连 而没有连接到其它设备或共享网段上 也必须等待2 倍的ForwardDelay 的时间延迟 端口才能迁移到转发状态 RSTP Rapid Spanni
  • Python 异步: 异步上下文管理器(17)

    动动发财的小手 点个赞吧 上下文管理器是一种 Python 构造 它提供了一个类似 try finally 的环境 具有一致的接口和方便的语法 例如通过 with 表达 它通常与资源一起使用 确保在我们完成资源后始终关闭或释放资源 无论资源
  • VC++ OpenCV+ZBar二维码识别

    利用OpenCV处理图像的优势 结合ZBar提高二维码识别结果 接口定义 include
  • SpringSecurity配置类--常用配置

    SpringSecurity配置类 在学习这门课的时候 实现各种功能时进行了各种配置 我想将各种配置综合讲述一下 首先自定义配置类 需要继承WebSecurityConfigurerAdapter这个类 在这个类里面做了一些默认配置 Con
  • linux grpc,grpc linux下的编译使用-Go语言中文社区

    1 一些工具安装 apt get install build essential autoconf libtool pkg config apt get install libgflags dev libgtest dev apt get
  • [转]IDEA 撤销 merge 操作(详解)

    目录 一 前言 二 解决方案 通过 Git Bash 命令行解决 1 合并过程中未发生冲突 2 合并过程中发生冲突 三 解决方案 通过 IDEA 解决 附带详细的操作图 1 合并过程中未发生冲突 2 合并过程中发生冲突 四 最后 作为一个开
  • 自己制作的 macOS Mojave 10.15.3 iso 文件,亲测可用(附 VMware15 安装 macOS Catalina 图文教程与 macO Catalina.iso 镜像下载地址)

    注 如果需要分享此资源 请注明原作者 不要把别人的东西当做自己的成果 也不要把别人免费分享出来的东西以有偿的方式去分享 自己制作的 macOS Mojave 10 15 3 iso 文件 亲测可用 已在 VMware 15 5 Player
  • AOSP 预置APP安装 以MicroG GmsCore.apk安装为例

    AOSP 预置APP 以MicroG为例 MicroG 无root安装教程 通过源码修改打开签名欺骗 预置不带源码的APP 其他 AOSP 安装谷歌三件套失败 开始寻找代替方案 尝试使用MicroG项目代替谷歌服务 目前情况 已成功安装 所
  • 第十八节 多核异构核间通信–ipcc

    由于MP157 是一款多核异构的芯片 其中既包含的高性能的A7 核及实时性强的M4 内核 那么这两种处理器在工作时 怎么互相协调配合呢 这就涉及到了核间通信的概念了 IPCC inter processor communication co
  • 【医学影像数据处理】2D/3D patch的crop和merge操作汇总

    在做3D分割任务中 多数的方法多采用整体缩放 或裁剪成一个个小的patch操作 这样做的一个主要原因是内存问题 相较于整体缩放 采用裁剪成patch的方法 对于小目标会更加的鲁棒 这也是大多数3D分割任务中常选取的方式 尤其是针对医学影像的
  • spring boot项目同时传递参数和文件的多种方式

    在开发接口中 遇到了需要同时接收参数和文件的情况 可以有多种方式实现文件 参数的接收 这里基于spring boot 3 vue 3 axios 做一个简单的代码演示 1 简单参数 文件参数 参数较少时 比较方便 直接参数接受即可 1 1
  • Mac上亲测好用的BlueStacks蓝叠安卓模拟器

    bluestacks mac是一款基于macOS系统打造的安卓模拟器 其优秀的稳定性 良好的兼容性一直是玩家的模拟器的首选哦 BlueStacks 4 for mac使Mac用户能够在他们的Mac上下载并享受他们喜欢的Android应用程序

随机推荐

  • vs2019运行asp.net framework(c# 基础) 排课系统的完整步骤

    前言 没想过有朝一日还会学net 毕竟java太强了 但因为特殊需要 还是学了一下net 发现她两真的好像呀 源码仓库 https gitee com web paul scheduling system 前期准备 vs2019 需要asp
  • Handler和Controller的区别

    以前一直以为这两个概念貌似是没有太大的区别 调研发现还是有一些区别的 Handler HandlerMapping接口实现从URL映射到请求处理程序bean 支持映射到bean实例和bean names Controller Base Co
  • 2021-08-10基于人脸识别的学生签到系统

    这是这学期web前端开发的大作业 因为要考研时间有限 很多功能只是先把页面做好了 没事实现和数据库的连接 用的数据大多数是在json中存储的 需求分析 一 教师端 功能需求 1登录 数据需求 用户名 密码 邮箱号 2能够管理课程 增加 删除
  • string16类型转string

    std string WChar2Ansi LPCWSTR pwszSrc int nLen WideCharToMultiByte CP ACP 0 pwszSrc 1 NULL 0 NULL NULL if nLen lt 0 retu
  • android 屏幕适配(亲测最兼容方便)

    Android屏幕适配有很多方式 1 设置屏幕固定尺寸适配 例如适配1280x720 只适合少量固定屏幕的设备 2 百分比布局 开发中多了很多代码 3 通过密度值px转dp来适配 方便兼容 基本准确 4 通过修改系统密度值适配 例如抖音适配
  • 【Linux】定时任务crontab/at

    在linux系统中定时任务常用两个命令crontab及at命令 两者区别在于crontab用于设置循环定时任务 即每隔一定时间或固定时间后启动对应任务命令 at用于设置一次性定时任务 在任务完成后定时任务即删除 1 crontab命令 1
  • 【送书活动】借助ChatGPT和Python,轻松实现办公自动化✨

    前言 作者主页 雪碧有白泡泡 个人网站 雪碧的个人网站 推荐专栏 java一站式服务 React从入门到精通 前端炫酷代码分享 从0到英雄 vue成神之路 uniapp 从构建到提升 从0到英雄 vue成神之路 解决算法 一个专栏就够了 架
  • malloc和strcpy,入门的指针面试题

    指针是C和C 编程语言中一个重要的概念 因此在面试以及工作中经常会涉及到指针相关的问题 现在列举几个比较基础问题 一 void getMemory char p p char malloc 100 void test void char s
  • 【使用Excel批量修改文件名称——超详细教程——无需复杂操作;bat,ren指令】

    基本指令 bat concatenate concatenate 该公式用于给新文件名名称添加后缀 ren公式 ren A2 B2 要注意的是ren后边有一个空格 后边有一个空格 此公式用于合并旧文件与新文件名称 操作步骤 首先创建一个文本
  • C语言 函数 下

    函数的定义 如果函数的定义在main函数之后 函数要在main函数前先进行声明 写一个函数完成两个整数的相加 int Add int a int b 函数的声明 int main printf 请您输入a b的值 int a 0 int b
  • Python入门---初识

    Python简介 Python的历史 1989年圣诞节 Guido von Rossum开始写Python语言的编译器 1991年2月 第一个Python编译器 同时也是解释器 诞生 它是用C语言实现的 后面 可以调用C语言的库函数 在最早
  • python入门教程(非常详细)

    Python是一种高级 解释性的脚本语言 其简单易学 灵活 强大等特点 使其成为了当代最流行的编程语言之一 如果您是想学习Python编程的新手 以下是详细的Python入门教程 以帮助您快速掌握Python编程基础 1 安装Python
  • STM32 基础系列教程 50 – MbedTls

    前言 mbed TLS 以前称为PolarSSL 是TLS和SSL协议的实现 并且需要相应的加密算法和支持代码 这是双重许可与Apache许可证 2 0版 与GPLv2许可也可 网站上指出 mbed TLS的目标是 易于理解 使用 集成和扩
  • 详解 C 语言中的弱符号与弱引用

    C语言中的 attribute weak 与 attribute weakref 引言 最近在看 linux 中一些驱动代码 驱动代码中为了实现程序的扩展性和兼容性用了很多 C 语言中的高级特性 本节就来谈一谈 C 语言中的弱符号和弱引用的
  • 机器学习在工程中使用要点

    机器学习现在有很多分支 大部分使用数据和模型优化入手 在此之前机器学习按照学派划分是有可靠的理论依据的 那么我们使用应该注意以下几点 1 如何获取训练集 一般我们下载现有的训练集为了学习或者来测试自己的算法泛化能力的表现水平 这时候我们对训
  • Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS

    首先介绍一些乐观锁与悲观锁 悲观锁 总是假设最坏的情况 每次去拿数据的时候都认为别人会修改 所以每次在拿数据的时候都会上锁 这样别人想拿这个数据就会阻塞直到它拿到锁 传统的关系型数据库里边就用到了很多这种锁机制 比如行锁 表锁等 读锁 写锁
  • 每日站会是在浪费时间...吗?

    原文链接作者 Mark Levison 又要开站会 实在是浪费时间 打断我的工作啦 每日站会只是为ScrumMaster刷存在感而设计的 便于他微观管理 每日站会上就是汇报一下状态 而我写个邮件就行了啊 你以前听说过这些抱怨吗 我听过 不过
  • Java中获取数组长度

    Java中获取数组长度 方法 使用数组属性length来获取数组长度 代码 public class ArrayLength public static void main String args String data new Strin
  • Linux服务器之间的文件同步(单向同步:rsync+inotify)

    1 rsync简介 rsync是linux系统下的数据备份工具 支持本地复制 或者与其他SSH rsync主机同步 2 rsync的部分特性 rsync支持很多特性 可以镜像保存整个目录树和文件系统 可以很容易做到保持原来文件的权限 时间
  • APICloud(四):图片上传-Java版

    这一篇讲 将选择的图片上传到指定的服务器 说实话 这个功能写了好久 一会儿json拼的有问题访问不到后台 一会儿后台又说form表单的enctype不是multipart form data类型 各种乱七八糟的问题折腾了一下午都没好 第二天