相信从事Web开发的都会碰到上传文件这类的基础问题,恰好在公司实习涉及到上传文件,通过查阅网上相关的资料,特整理如下,
1 Spring文件中添加如下配置,勿忘,否者怀疑人生,死都不知道怎么死的:
<!-- 配置MultipartResolver 用于文件上传 使用spring的CommosMultipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize"><value>100000</value></property>
<property name="defaultEncoding"><value>UTF-8</value></property>
</bean>
添加两个架包:
commons-fileupload-1.1.1.jar
commons-io-1.3.2.jar
2 JSP页面及form表单:
</head>
<body>
<form method="POST" action="upLoadFile_01.do" enctype="multipart/form-data">
选择一个文件:
<input type="file" name="upLoadFile" />
<input type="text" name="number" />
<br/><br/>
<input type="submit" value="上传" />
</form>
<form method="POST" action="upLoadFile_02.do" enctype="multipart/form-data">
选择一个文件:
<input type="file" name="upLoadFile" />
<input type="text" name="number" />
<br/><br/>
<input type="submit" value="上传" />
</form>
<form method="POST" action="upLoadFile_03.do" enctype="multipart/form-data">
选择一个文件:
<input type="file" name="upLoadFile" />
<input type="text" name="number" />
<br/><br/>
<input type="submit" value="上传" />
</form>
<form method="POST" action="upLoadFile_04.do" enctype="multipart/form-data">
选择一个文件:
<input type="file" name="upLoadFile" />
<input type="text" name="number" />
<br/><br/>
<input type="submit" value="上传" />
</form>
<form method="POST" action="upLoadFile_05.do" enctype="multipart/form-data">
选择一个文件:
<input type="file" name="upLoadFile" />
<input type="text" name="number" />
<br/><br/>
<input type="submit" value="上传" />
</form>
<form method="POST" action="upLoadFile_06.do" enctype="multipart/form-data">
选择一个文件:
<input type="file" name="upLoadFile" />
<input type="text" name="number" />
<br/><br/>
<input type="submit" value="上传" />
</form>
</body>
注意:
看看表单<from>中是否包含 enctype="multipart/form-data"
enctype="multipart/form-data" 会让数据以二进制传输,
2.1 JS判断上传文件的大小:
CSS代码:
<input name="attach" class=" box2" type="file" onchange="checkFileSize(this);" />
JS代码:
var isIE = /msie/i.test(navigator.userAgent) && !window.opera;
//检测上传文件的大小
function checkFileSize(target) {
//获取的大小单位为b
var fileSize = 0;
if (isIE && !target.files) {
var filePath = target.val();
var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
var file = fileSystem.GetFile(filePath);
fileSize = file.Size;
} else {
fileSize = target.files[0].size;
}
//获取的文件大小单位b
//限制的大小为30MB
var fileMaxSize = 30 * 1024 * 1024;
if (fileSize > fileMaxSize) {
//超过指定大小,删除附件
alert("上传文件过大,请限制在30MB以下","",1);
//上传附件文件过大,删除附件
deleteAttach();
return false;
}
return true;
}
3 Controller层:
方式一:
/**
* 多文件上传与单文件上传类似,多文件上传将表单中的
* input标签中的name="upLoadFile"属性设为相同,在控制器中将MultipartFile定义为一个数组 循环读取,依次上传
*
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping(value = "upLoadFile_01", method = RequestMethod.POST)
public String upLoadFile_01(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value = "upLoadFile", required = false) MultipartFile file,
String number) throws IOException {
System.out.println("进入" + number);
if (file != null) {
System.out.println("正在上传");
System.out.println(file.getName());
System.out.println(file.getOriginalFilename());
File fileDir = new File(UPLOAD_FILE_PATH);
// 目录是否存在
if (!fileDir.exists()) {
// 创建文件
fileDir.mkdir();
}
FileOutputStream fileOutputStream = new FileOutputStream(
UPLOAD_FILE_PATH + file.getOriginalFilename());
byte[] bytes = file.getBytes();
BufferedOutputStream stream = new BufferedOutputStream(
fileOutputStream);
stream.write(bytes);
stream.close();
fileOutputStream.close();
System.out.println("上传完成");
return "list";
} else {
System.out.println("没有上传文件");
request.setAttribute("answer", "上传失败");
return "list";
}
}
方式二:
/**
* 多文件上传与单文件上传类似,多文件上传将表单中的
* input标签中的name="upLoadFile"属性设为相同,在控制器中将MultipartFile定义为一个数组 循环读取,依次上传
*
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping(value = "upLoadFile_02", method = RequestMethod.POST)
public String upLoadFile_02(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value = "upLoadFile", required = false) MultipartFile file,
String number) throws IOException {
System.out.println("进入" + number);
InputStream inputStream = file.getInputStream();
File file2 = new File(UPLOAD_FILE_PATH);
// 当目录不存在时创建
if (!file2.exists()) {
file2.mkdir();
}
// 写入指定的目录
FileOutputStream fileOutputStream = new FileOutputStream(
UPLOAD_FILE_PATH + file.getOriginalFilename());
byte[] buff = new byte[1024];
int hasReand = 0;
while ((hasReand = inputStream.read(buff)) > 0) {
fileOutputStream.write(buff);
}
fileOutputStream.close();
inputStream.close();
System.out.println("上传成功");
return "list";
}
方式三:
/**
* 多文件上传与单文件上传类似,多文件上传将表单中的
* input标签中的name="upLoadFile"属性设为相同,在控制器中将MultipartFile定义为一个数组 循环读取,依次上传
*
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping(value = "upLoadFile_03", method = RequestMethod.POST)
public String upLoadFile_03(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value = "upLoadFile", required = false) MultipartFile file,
String number) throws IOException {
System.out.println("进入" + number);
File fileDir = new File(UPLOAD_FILE_PATH);
// 当目录不存在时创建
if (!fileDir.exists()) {
fileDir.mkdir();
}
File file2 = new File(UPLOAD_FILE_PATH + file.getOriginalFilename());
file.transferTo(file2);
System.out.println("上传成功");
return "list";
}
方式四:
/**
* 多文件上传与单文件上传类似,多文件上传将表单中的
* input标签中的name="upLoadFile"属性设为相同,在控制器中将MultipartFile定义为一个数组 循环读取,依次上传
*
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping(value = "upLoadFile_04", method = RequestMethod.POST)
public String upLoadFile_04(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value = "upLoadFile", required = false) MultipartFile file,
String number) throws IOException {
System.out.println("进入" + number);
File fileDir = new File(UPLOAD_FILE_PATH);
// 当目录不存在时创建
if (!fileDir.exists()) {
fileDir.mkdir();
}
File file2 = new File(UPLOAD_FILE_PATH + file.getOriginalFilename());
file.transferTo(file2);
System.out.println("上传成功");
return "list";
}
方式五:
/**
* 只能上传文档 多文件上传与单文件上传类似,多文件上传将表单中的
* input标签中的name="upLoadFile"属性设为相同,在控制器中将MultipartFile定义为一个数组 循环读取,依次上传
*
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping(value = "upLoadFile_05", method = RequestMethod.POST)
public String upLoadFile_05(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value = "upLoadFile", required = false) MultipartFile file,
String number) throws IOException {
System.out.println("进入" + number);
File fileDir = new File(UPLOAD_FILE_PATH);
// 当目录不存在时创建
if (!fileDir.exists()) {
fileDir.mkdir();
}
FileWriter fileWriter = new FileWriter(UPLOAD_FILE_PATH
+ file.getOriginalFilename());
InputStream inputStream = file.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(
inputStream, "GB2312");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
int hasRead = 0;
char[] buff2 = new char[1024];
while ((hasRead = bufferedReader.read(buff2)) > 0) {
fileWriter.write(buff2);
}
fileWriter.close();
bufferedReader.close();
System.out.println("上传成功");
return "list";
}
方式六:
/**
* 只能上传文档 多文件上传与单文件上传类似,多文件上传将表单中的
* input标签中的name="upLoadFile"属性设为相同,在控制器中将MultipartFile定义为一个数组 循环读取,依次上传
* @param request
* @param response
* @return
* @throws Exception
*/
@RequestMapping(value = "upLoadFile_06", method = RequestMethod.POST)
public String upLoadFile_06(HttpServletRequest request,
HttpServletResponse response, String number) throws Exception {
System.out.println("进入" + number);
File fileDir = new File(UPLOAD_FILE_PATH);
// 当目录不存在时创建
if (!fileDir.exists()) {
fileDir.mkdir();
}
DiskFileItemFactory factory = new DiskFileItemFactory();
// 最大缓存
factory.setSizeThreshold(5 * 1024);
// 临时文件目录
File fileTempDir = new File(UPLOAD_FILE_PATH + "temp");
if (!fileTempDir.exists()) {
fileTempDir.mkdir();
}
factory.setRepository(fileTempDir);
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// 获取所有文件列表
List<FileItem> itemFileItems = fileUpload.parseRequest(request);
for (FileItem item : itemFileItems) {
if (!item.isFormField()) {
// 文件名
String fileName = item.getName();
// 文件后缀
String fileEnd = fileName.substring(
(fileName.lastIndexOf(".") + 1)).toLowerCase();
// 创建文件唯一名称
String uuid = UUID.randomUUID().toString();
StringBuffer fileNewName = new StringBuffer();
fileNewName.append(UPLOAD_FILE_PATH).append(uuid).append(".")
.append(fileEnd);
// 写入文件
File file2 = new File(fileNewName.toString());
item.write(file2);
}
}
System.out.println("上传成功");
return "list";
}
个人比较喜欢方式五,简单粗暴,直接明了。
上传文件和表单数据
表单:
<form id="formData" enctype="multipart/form-data" >
<input type="text" name="name" id="name"/>
<input type="password" name="password" id="password"/>
<input type="file" name="file" id="file"/>
<input type="button" onclick="submitData()" value="确认">
</form>
JS代码:
//JSON字符串转JSON对象
function strToJSON01(str){
return eval('('+str+')');
}
//JSON字符串转JSON对象
function strToJSON02(str){
return JSON.parse(str);
}
function submitData(){
console.log($('#formData').serialize());//name=admin&password=123456 console.log(formToJson($('#formData')));//{"name":"admin","password":"123456"}
console.log(typeof(formToJson($('#formData'))));//为JSON字符串
console.log(typeof(strToJSON01(formToJson($('#formData')))));//为JSON对象 {name: "admin", password: "123456"}
console.log({'name':$('#name').val(),'password':$('#password').val()});//:{name: "name", value: "admin"}1:{name: "password", value: "123456"}
console.log(typeof{'name':$('#name').val(),'password':$('#password').val()});//为JSON对象
$.ajaxFileUpload({
url:'<%=basePath %>text/upload.html',
type:'POST',
secureuri:false,//是否启用安全提交,默认为false。
fileElementId:'file',//文件标签的name
dataType:'text',//服务器返回的数据类型
data:strToJSON01(formToJson($('#formData'))),//将form表单序列化为JSON字符串后转为JSON对象
//data:{'name':$('#name').val(),'password':$('#password').val()},与上面的相同
success : function(data, status) {
console.log(data+" "+status);
},
error : function(data, status, e) {
console.log(data+" "+status);
},
});
}
//将表单数据转化为JSON数据 form为表单对象,如$("#form01"),返回序列化数据
function formToJson(form) {
var data = form.serialize();
data = decodeURIComponent(data, true);//防止中文乱码
data = data.replace(/&/g, "','");
data = data.replace(/=/g, "':'");
data = "({'" + data + "'})";
obj = eval(data);
obj=JSON.stringify(obj);
return obj;
}
后台代码:表单中页面编码方式设置为enctype=”multipart/form-data”后,取数据只能通过这样的形式来取:
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
multipartRequest.getParameter("name")
@ResponseBody
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public void formData(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value = "file", required = false) MultipartFile file) {
//System.out.println(user.getName() + " " + user.getPassword());
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
System.out.println("name"+multipartRequest.getParameter("name"));
System.out.println("password"+multipartRequest.getParameter("password"));
System.out.println(multipartRequest.getFile("file"));//file为表单中name的值,同样可取到上传的文件
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
Integer hasRead = 0;
byte[] buff = new byte[1024];
while ((hasRead = inputStream.read(buff)) > 0) {
//System.out.println(new String(buff,0,hasRead));
}
} catch (Exception exception) {
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
参考:http://blog.csdn.net/wabiaozia/article/details/50221945
附出现的问题及解决方案:
1 错误The request sent by the client was syntactically incorrect ()的解决
这个错误是SpringMVC报出来的,见到它意味着html/jsp页面的控件名称 和 controller里函数的参数不符。
http://www.cnblogs.com/xiandedanteng/p/4168609.html
2
java.io.FileNotFoundException: D:\uploadFile (拒绝访问。)
at java.io.FileOutputStream.open0(Native Method)
at java.io.FileOutputStream.open(FileOutputStream.java:270)
at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
原因在实例化File file=new File(fileAllName);的时候fileAllName是一个目录
而在下面这就就报上面的异常了。
FileWriter fw=new FileWriter(file);
解决办法,将fileAllName具体到文件名字。
参考网站:http://blog.csdn.net/truong/article/details/8524750
3
InputStream inputStream = file.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
bufferedreader出现乱码
解决方案:
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,”GB2312”);
参考网站:http://nneverwei.iteye.com/blog/490884
4 下载文件
触发一个请求,系统读取文件,然后通过输入输出流输出到响应中。
@RequestMapping("download")
public void download(HttpServletRequest request,
HttpServletResponse response) {
OutputStream outputStream = null;
InputStream inputStream=null;
try {
outputStream = response.getOutputStream();
response.setContentType("application/octet-stream;charset=UTF-8");// 设置文件输出类型
response.setHeader("Content-disposition", "attachment; filename="
+ new String("错误工资记录.txt".getBytes("utf-8"), "ISO8859-1"));//设置下载的文件名
/*String basePath01 = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ request.getContextPath() + "/";
String basePath02=this.getRequestBasePath(request);*/
String baseAbsoluteFilePath=request.getServletContext().getRealPath("");//获取的是项目在磁盘中的绝对路径,最后包括"\"
String fileRelativePath="doc/html.txt";//文件相对于webRoot的路径
inputStream=new FileInputStream(baseAbsoluteFilePath+fileRelativePath);
byte[] buff=new byte[1024];
Integer readLength=0;
while((readLength=inputStream.read(buff,0,buff.length))>0){
outputStream.write(buff, 0, readLength);
}
outputStream.close();
inputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
下载时不可用ajax,应该用ajaxfileupload。
如果被下载的文件在WebRoot下,可通过request.getServletContext().getRealPath(“”);获取项目在磁盘中的绝对路径,
参考:http://blog.csdn.net/tomcat_2014/article/details/50624120
下载参考:http://www.cnblogs.com/jxldjsn/p/5671578.html