文件上传(JQuery AJAX 的使用)。

今天在写一个文件上传的时候遇到了 问题 ! 无论如何都检索不到有上传的文件。上传的结果都只有文件的路径,上传的文件夹内一直没有文件。琢磨了好长时间,才解决问题。

客户端。

  1. 首先,我们看下页面的代码。这里以上传图片的代码为例。

我使用的是 layui 的官方框架。
form 表单提交,带有附件的时候,需要设置 enctype="multipart/form-data" 图中已给出。

Form上传文件
2. 紧接着,开始 使用 JQuery Ajax 对图片进行异步上传。
在这里插入图片描述
3. 这样后台就能够接收到带有附件表单上传的数据。
在这里插入图片描述

一、之前我经常使用的 AJAX 是这样的。

  1. 写一个简单的 ajax 访问:
$.ajax({
	url:"",		// 请求后台方法。
	type:"get",	// 请求方式
	cache:false,	// 控制是否缓存数据
	async:false,	// 控制同步还是异步
	data:{
		id:1
		//  传入数据
	},
	success:function(data){
		if(data != null && data != ""){
			$(".showdata").html(data);	// 从后台成功获取数据的回调函数
		}
	},
	error:function(){
		alert("网络错误,请重试 !!");
	}
});
  1. 使用的时候 需要注意两点信息
  • cache属性,默认是 true ,就是页面需要缓存。有些时候修改了值,但是值没变,都是由于缓存的原因。ajax 请求存在着许多缓存问题。请求方式为 post 的时候,默认为 false ;请求方式为 get 的时候,默认为 true 。
  • async属性,默认是 true,决定本次执行的 ajax 请求是异步的。同步指的是:像后台代码一样,一行一行的执行。异步指的是:ajax 请求还没有执行完成就去执行下一句 js 。
  1. ajax 简单来说,就是请求后台,获取数据回调,然后页面展示。

二、但是 AJAX 文件上传更应该注意下面的内容。

  1. 经常用 ajax 的人都知道,ajax 的默认编码方式是 “application/x-www-form-urlencoded”,此编码方式只能编码文本类型的数据,因此 ajax 发送请求的时候,会把 data 序列化成一个个 String 类型的键值对,大部门应用都可以满足。
  2. 就是上述的原因,导致今天的错误。所以此序列化机制是文件上传的绊脚石。
  3. 我们需要做的是,(1)获取表单的内容,赋值给 ajax 的data;(2)阻止将参数转成String类型的键值对。
  • FormData 是 html5 的接口,使用它一行代码便可以拿到整个表单的内容。
var form = new FormData(document.getElementById("mulform"));
//  mulform 是表单的 id 。
  • 设置 process 属性,阻止转成 String 类型的字符串。同时设置 ajax 的编码方式为false(contentType:fals),在 form 表单里已经设置了编码方式,ajax 的编码机制已经不需要。
$.ajax({
	url : "../../addActivity.action",
	type : "post",		// 默认 对应的 cache:false
	dataType : "json",
	processData:false,
	contentType:false,
	data:form,
	success : function(data){
		location.reload();
	},
	error:function(){
		top.layer.msg("网络错误,请重试 !!");
	}
});
  • 务必 使用 post 的请求方式,

contentType 的编码方式:

  1. application/x-www-form-urlencoded:String 类型的键值对。
  2. multipart/form-data:支持文件上传。
  3. application/json类型主要是传递json数据用到,层次比较深的数据。
  4. text/plain:窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。

2.1 其中的关键要素。

  1. contentType:(默认的编码方式 “application/x-www-form-urlencoded”)发送信息至服务器时内容编码类型。
  2. processData:(默认 true )默认情况下,通过 data 属性传进来的数据,都会转化成一个字符串,配合默认内容类型"application/x-www-form-urlencoded",如果要发送 DOM 树、文件内容或其他希望转换的信息,需要设置为 true 。
  3. FormData :利用 这个对象,我们可以通过 JavaScript 用一些键值对来模拟一系类表单控件,还可以异步上传一个 二进制文件。

更多内容请参考 W3C

2.2 这里补充一个既能获取文件,又能获取表单数据的方式

  • 这里通过 new FormData 创建了 fileFrom 表单的对象。
    在这里插入图片描述
  • 下图就是断点停留的地方,可以看到文件与表单的内容都可以获取到的,只不过需要设置一下实体类中的文件路径。
    在这里插入图片描述

服务器。

目前呢,我对上传文件的操作还只是初步了解,如果哪位大神有更好的方法,希望能够分享给我的啦。

需要两个 Jar 包。

1. commons-fileupload.jar 包文件。
<dependency>
	<groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>
2. commons-io.jar 包文件。
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

SpringMVC 配置文件解析器CommonsMultipartResolver

<!-- 多部分文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <property name="maxUploadSize" value="104857600" />
     <property name="maxInMemorySize" value="4096" />
     <property name="defaultEncoding" value="UTF-8"></property>
</bean>

单文件接收 MultipartFile 以及 多文件接收 MutipartFile[]

  1. 对于MulipartFile,只需要这样就可以了:MultipartFile file, HttpServletRequest request
@RequestMapping("uploadFile")
public String  fileUpload(MultipartFile file, HttpServletRequest request) throws IOException {
}
  1. 对于CommonsMultipartFile,需要@RequestParam(“file”) CommonsMultipartFile Filedata, HttpServletRequest request,不然不会进此方法。
@RequestMapping("uploadFile")
public String  fileUpload(@RequestParam("file") CommonsMultipartFile Filedata, HttpServletRequest request) throws IOException {
}

通过流的方式上传文件

@RequestParam(“file”) 将name=file控件得到的文件封装成CommonsMultipartFile 对象
通过字节流的方式,读取文件 file.getInputStream(); ,之后通过 OutputStream 写在指定目录。

@RequestMapping("fileUpload")
public String  fileUpload(@RequestParam("file") CommonsMultipartFile file) throws IOException {
    //	文件上传的开始时间
    long  startTime=System.currentTimeMillis();
    System.out.println("fileName:"+file.getOriginalFilename());
    try {
        //获取输出流
        OutputStream os=new FileOutputStream("D:/"+new Date().getTime()+file.getOriginalFilename());
        //获取输入流 CommonsMultipartFile 中可以直接得到文件的流
        InputStream is = file.getInputStream();
        int temp;
        //一个一个字节的读取并写入
        while((temp=is.read())!=(-1))
        {
            os.write(temp);
        }
       os.flush();
       os.close();
       is.close();
    } catch (FileNotFoundException e) {
        throw new Exception("异常:文件找不到");
    }
    long  endTime=System.currentTimeMillis();
    System.out.println("方法一的运行时间:"+String.valueOf(endTime-startTime)+"ms");
    return "/success"; 
}

file.transferTo 方式上传文件

只需要规定文件上传文件的路径就可以对文件进行上传。

 @RequestMapping("fileUpload2")
 public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file) throws IOException {
      long  startTime=System.currentTimeMillis();
     System.out.println("fileName:"+file.getOriginalFilename());
     String path="D:/"+new Date().getTime()+file.getOriginalFilename();
     File newFile=new File(path);
     // file.transTo 方式上传文件,直接写文件
     file.transferTo(newFile);
     long  endTime=System.currentTimeMillis();
     System.out.println("方法二的运行时间:"+String.valueOf(endTime-startTime)+"ms");
     return "/success"; 
 }

使用 SpringMVC 同时上传文件与数据。

## 文本数据上传表单数据过大,使用 POST 提交
@RequestMapping(value="/upload" ,method=RequestMethod.POST)
public String test(User user,@RequestParam(value="uploadFile",required=false) MultipartFile uploadFile) throws Exception, IOException{
	System.out.println("上传文件操作开始……");
	String path = null;	// 设置存储路径为空
	if(!(uploadFile.isEmpty())){
		System.out.println("上传的文件不为空,进行路径操作");
		//	获取保存文件的绝对路径,存放到项目路径下。File.separator 是 io 文件下的字符串 \
		String path = request.getSession().getServletContext().getRealPath("statics"+File.separator+"uploadfiles");
		System.out.println("2.1 uploadFile path ===>"+path);
		//	获取上传文件的文件名
		String oldFileName = uploadFile.getOriginalFilename();//原文件名
		System.out.println("2.2 uploadFile oldFileName ===>"+oldFileName);
		//	获取文件名后缀
		String suffix = oldFileName.substring(oldFileName.lastIndexof('.')); //	原文件名后缀
		System.out.println("2.3 uploadFile suffix ===>"+suffix );
		//设置文件大小的变量,KB是单位
		int filesize = 5000000;
		System.out.println("2.4 uploadFile filesize ===>"+uploadFile.getSize());
		if(uploadFile.getSize() > filesize){
			request.setAttribute("uploadFileError", "* 上传大小不得超过5000KB");
			System.out.println("* 上传大小不得超过5000KB");
			return "useradd";
		}else if(prefix.equalsIgnoreCase("jpg")
				   || prefix.equalsIgnoreCase("png")
				   || prefix.equalsIgnoreCase("jpeg")){
			// 上传格式正确,重新取得一个文件的路径。
			String fileName = System.currentTimeMillis()+RandomUtils.nextInt(1000000)+".jpg";
			System.out.println("2.5 new fileName===>"+uploadFile.getName());
			//	新建一个文件,File API,这样就可以为文件重定义名字。
			File targetFile = new File(path,fileName); 
			if(!targetFile.exists()){		// 判断文件是否存在,存在就上传覆盖了,
				targetFile.mkdirs(); 		// 不存在就创建。
			}
			//保存
			try{
				//  上传
				uploadFile.transferTo(targetFile);
			}catch (Exception e){
				e.printStackTrace();
				request.setAttribute("uploadFileError", "* 上传失败! ");
				System.out.println("* 上传失败! ");
				return "useradd";
			}
			path = path+File.separator+fileName;
		}else{
			request.setAttribute("uploadFileError", "* 上传格式错误!");
			System.out.println("* 上传格式错误!");
			return "useradd";
		}
	}
	user.setPicPath(path);
	System.out.println("user is: "+user);
	return "userlist";	
}
  • 其中 ,File 有固定的字符串可以使用。
    在这里插入图片描述
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值