html5-upload-images

html5-upload-images – 前端实现

html5+jquery 图片上传功能实现: 项目需要,开发一个手机端上传图片功能;经过百度学习,最终选择使用html5的input标签、FormData和FileReader来实现图片的上传和预览功能。

目前Android、IOS自带的浏览器均支持html5。html5 提供了input标签,将input标签的type属性设置为file,accept属性设置为image/*(接收所有的图片格式的文件)。

1
<input id="file" type="file" accept="image/*" />

通过html5的 this.files[] 数组去获取上传的文件对象,FormData对象通过append方法加载文件;通过jquery的Ajax进行post的提交文件,需要将 processDatacontentType 设置为false,即告诉ajax对文件formData不进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
var oFile = this.files[0];
var formData = new FormData(document.getElementById("upload_form"));
formData.append("oFile", oFile);
$.ajax({
url : "url",
type : "post",
data : formData,
processData : false,
contentType : false,
success : function(data) {
},
error : function(data) {
});
</script>

图片的预览,通过 FileReader的readAsDataURL 方法可以将读取到的文件编码成Data URL。Data URL是一项特殊的技术,可以将资料(例如图片)内嵌在网页之中,不用放到外部文件。使用Data URL的好处是,您不需要额外再发出一个HTTP 请求到服务器端取得额外的资料;而缺点便是,网页的大小可能会变大。它适合应用在内嵌小图片,不建议将大图像文件编码成Data URL来使用。您的图像文件不能够超过浏览器限定的大小,否则无法读取图像文件。

1
2
3
4
5
6
7
8
9
10
<script type="text/javascript">
var img = document.createElement("img");
var reader = new FileReader();
reader.onload = function(e) {
img.src = this.result;
};
reader.readAsDataURL(oFile);
img.width = 200;
div.append(img);
</script>

完整的前端代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<!DOCTYPE HTML PUBLIC "-//W3C//Ddiv XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/Ddiv/xhtml1-transitional.ddiv">
<html xml:lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet"
href="http://apps.bdimg.com/libs/jquerymobile/1.4.5/jquery.mobile-1.4.5.min.css">

<script src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"></script>
<script
src="http://apps.bdimg.com/libs/jquerymobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

<title>上传图片</title>
</head>
<body>
<div id="upload-container">
<input id="file" type="file" accept="image/*" />
<div id="space"></div>
</div>
<div id="upload_form"></div>
<script>
$("#file").change(
function() {
div = $("#space");
div.empty();
var oFile = this.files[0];
var formData = new FormData(document
.getElementById("upload_form"));
formData.append("oFile", oFile);
div.css("text-align","center");

var img = document.createElement("img");
var reader = new FileReader();
reader.onload = function(e) {
img.src = this.result;
};
reader.readAsDataURL(oFile);
img.width = 200;
div.append(img);

$("#upload-container").append(div);

br = document.createElement('br');
span = document.createElement('span');
span.style.color = "Red";

$.ajax({
url : "/visitor/upload/dealUpload",
type : "post",
data : formData,
processData : false,
contentType : false,
success : function(data) {
span.innerHTML = "图片上传成功!";
div.append(br);
div.append(span);
},
error : function(data) {
span.innerHTML = "Error!图片上传失败!";
div.append(br);
div.append(span);
}
});
});
</script>

</body>
</html>

下篇将讲述后端如何处理post的文件数据,简单的通过 HttpServletRequest的getRequest() 的方法无法获取该文件参数;需要 org.apache.commons.fileupload 中的 new ServletFileUpload(new DiskFileItemFactory()).parseRequest(getRequest()) 的方法去获取文件参数列表,具体详见html5+jquery图片上传功能实现–后端实现。

html5-upload-images 后端实现

项目需要,开发一个手机端上传图片功能;后端基于jfinal框架,进行图片上传的处理:1、获取文件数据;2、创建文件;3、将数据写入本地文件。

#在html5+jquery 图片上传功能实现–前端实现中,实现了ajax post提交文件的前端代码。

使用普通的 getPara() 的方法无法获取file数据

在jfinal中一般通过 getPara() 或者 getParaMap()的方法去获取post过来数据值。经过调试发现参数列表为空,即此方法无法获取post过来的file类型的数据。

使用 org.apache.commons.fileupload 来进行file数据解析

对文件上传功能,在浏览器端提供了较好的支持,只要将FORM表单的enctype属性设置为 “multipart/form-data” 即可;但在Web服务器端如何获取浏览器上传的文件,需要进行复杂的编程处理。org.apache.commons.fileupload的FileUpload 可以帮助我们解析这样的请求,将每一个项目封装成一个实现了 FileItem 接口的对象,并以列表的形式返回。

1
2
//为该请求创建一个DiskFileItemFactory对象,通过它来解析请求。执行解析后,所有的表单项目都保存在一个List中。
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(getRequest());

获取文件信息

通过 ServletFileUpload 静态类来解析Request,工厂类 FileItemFactory 会对mulipart类的表单中的所有字段进行处理,不只是file字段。getName() 得到文件名,getString() 得到表单数据内容,isFormField() 可判断是否为普通的表单项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
for (FileItem item : items)
{
// 判断当前项目是普通表单项目还是上传文件;
if (item.isFormField())//如果为普通的表单,将数据名和值写入日志中。
{
ajaxUploadResult += "Field " + item.getFieldName()
+ " with value: " + item.getString()
+ " is successfully read\n\r";
log.info(ajaxUploadResult);
} else//如果为文件,则获取文件的输入流,将输入流写入相应路径的文件列表中;
{
InputStream inputStream = item.getInputStream();
String filePath = createFilePath();//产生存储文件的路径
String fileName = createFileName();//产生存储文件的文件名
String imagePath = uploadFile(inputStream, fileName,
filePath);//将inputStream写入filePath路径中名为fileName文件
File file = new File(imagePath);//在imagePath路径中创建图片文件
}

}

图片上传的具体代码实现

具体uploadFile方法的实现,从inputStream每次最多读取1024byte的数据,直至将byte数据全部写入 FileOutputStream 对象的文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* 上传图片
*
* @author esonzys modify_date 2015年12月22日
* @param fileData
* 图片base64编码的数据
* @param fileName
* 生成的文件名
* @param uploadPath
* 上传图片的路径
* @return
*/

@SuppressWarnings({ "restriction" })
private String uploadFile(InputStream fileData, String fileName, String uploadPath)
{

File file = new File(uploadPath);
if (!file.exists())
{
file.mkdirs();
}
//File.separator用来根据操作系统来判断路径分隔符为“/”或者“\”;
String imagePath = uploadPath + File.separator + fileName + ".jpg";

file = new File(imagePath);

try
{
FileOutputStream outputStream = new FileOutputStream(file);
int bytesRead = -1;
byte[] buffer = new byte[1024];
while ((bytesRead = fileData.read(buffer)) > 0)
{
outputStream.write(buffer, 0, bytesRead);
outputStream.flush();
}

outputStream.close();
} catch (IOException e)
{
// TODO Auto-generated catch block
log.error(e.getMessage());
e.printStackTrace();
}

return imagePath;
}

至此,就可以在服务器相应的filePath路径中找到上传的图片文件了。