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

本文详细介绍了在APICloud中实现图片上传到Java后台的过程,包括遇到的json格式错误、form表单类型问题等挑战,最终成功实现发布公告时的图片上传功能。代码提交和后台文件上传的步骤也在文中详述。
摘要由CSDN通过智能技术生成

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

说实话,这个功能写了好久,一会儿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;
    }
}

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值