上传表单获取文件数据
在我们完成项目的过程中,有时候会碰到需要上传图片、音频、视频、文件等保存到数据库,这时候我们就可以用流的方式读取或写入。但是用流的方式需要拿到文件在本机上的路径,而现在大部分的浏览器出于安全考虑是拿不到文件的完整路径的,所以就无法访问到本机上的文件。使用上传表单则可以读取到这个文件,不是使用上传表单有一些限制,跟我们平常的上传表单不完全相同。下面是对限制的说明
上传对表单的限制:
表单必须加上method="post"属性,表示以post提交方式上传;
必须加上enctype=“multipart/form-data”;表示多部件的表单数据
表单中需要添加文件表单项,什么是文件表单项?就是input标签类型为file的 控件,除了它叫文件表单项,其他的都叫普通表单项。文件表单项:,必须要给name属性。
上传对Servlet的限制:
获取传递过来的数据,我们使用的request.getParameter(“xxx”);,它的返回类型为String类型,而我们上传的文件到Servlet这边就成了String类型,那肯定是不行的。而且这个方法在表单为enctype="multipart/form-data"时作废了。他永远返回null;不管你传的是文件类型数据还是普通的数据返回的都是null。
这时就提供了另一个方法用来获取传递过来的数据:ServletInputStream in=request.getInputStream();这个方法返回的是流数据,数据包含整个请求的体。
上面已经说了相关的限制,现在说说servlet怎么拿到对应的数据吧。为了方便拿到数据我这里引用了两个工具jar包,分别是 commons-io-2.5.jar和 commons-fileupload-1.3.2.jar。我们既然要上传文件那肯定要跟流打交道,所以引了个io包,而fileupload包则会帮我们解析request中的上传数据,解析后的结果就是将一个表单项封装到一个FileItem对象中。而我们通常都有多个表单项,所以得出的是一个FileItem集合。我们遍历这个集合调用FileItem的方法就能拿到对应表单项中的数据了。
下面先给出FileItem对象常用的几个方法:
第一个: isFormField(),上面已经说了一个表单项封装到一个FileItem对象中,也就是一个FileItem对象对应我们前端的一个input控件中的数据。所以有一个方法能判断表单项为普通表单项还是文件表单项。返回true为普通表单项,否则为文件表单项。
第二个:getFieldName()返回表单项的名称,即前端input控件的name属性值,返回类型为String。
第三个:getString(String charset),返回表单项的值,返回类型为String,只适用于普通表单项。charset为编码格式。
第四个:getName(),返回上传的文件名称,返回类型为String。
第五个:getSize(),返回上传的字节数, 返回类型为long。
第六个:getInputStream(),返回上传文件的对应的输入流,返回类型为InputStream。
第七个:write(File destFile),把上传的文件内容保存到指定的文件夹中。destFile为指定的文件夹对象。
上面讲了一堆,想必大家也看烦了,那就直接上干货吧。我这里是一个新增功能:我这就贴出servlet中获取数据并赋值给对象的代码吧。当然图片保存到数据出我给对象赋的是图片的路径,然后用流读写保存。
public void addCommodity(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String msg = "数据异常!";
Commodity commodity = new Commodity();
int sizeThreshold = 1024 * 1024 * 10; // 10MB
int fileSizeMax = 1024 * 1024 * 100; // 100M
int sizeMax = 1024 * 1024 * 300; // 300M
DiskFileItemFactory factory = new DiskFileItemFactory();// 第一步:创建工厂,设置工厂配置
factory.setSizeThreshold(sizeThreshold); // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中 10M
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));// 配置临时目录
ServletFileUpload upload = new ServletFileUpload(factory);//第二步:创建解析器,设置解析器配置
upload.setHeaderEncoding("utf-8");// 设置编码
upload.setFileSizeMax(fileSizeMax); // 设置上传文件的最大大小
upload.setSizeMax(sizeMax); // 设置请求的最大大小
// 构造临时路径来存储上传的文件,这个路径相对当前应用的目录,也就是此项目的目录
String uploadPath = this.getServletContext().getRealPath("/upload");
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {// 如果目录不存在则创建
uploadDir.mkdir();
}
try {
// 第三步:使用解析器解析表单数据,得到FileItem集合
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {// 第四部:遍历FileItem集合,获取数据
if (!fileItem.isFormField()) {// isFormField 是否为普通表单项
// 处理路径及保存文件
String fileName = new File(fileItem.getName()).getName();
if (fileName != null) {//没有上传文件则不作操作
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
// 保存文件到目录中
fileItem.write(storeFile);
commodity.setCommoditypicture(storeFile.getAbsolutePath());
}
} else {
// 获取普通表单项字段以及给对象赋值
String fieldName = fileItem.getFieldName();
String val = fileItem.getString("UTF-8");
if (fieldName.equals("commodityid")) {
commodity.setCommodityid(Integer.valueOf(val));
}
if (fieldName.equals("seasonid")) {
commodity.setSeasonid(Short.valueOf(val));
}
if (fieldName.equals("discount")) {
commodity.setDiscount(Double.valueOf(val));
}
if (fieldName.equals("commoditystylenumber")) {
commodity.setCommoditystylenumber(val);
}
if (fieldName.equals("specialoffer")) {
if (Boolean.valueOf(val).equals("false")) {
commodity.setSpecialoffer(false);
} else {
commodity.setSpecialoffer(true);
}
}
if (fieldName.equals("putaway")) {
if (Boolean.valueOf(val).equals("false")) {
commodity.setPutaway(false);
} else {
commodity.setPutaway(true);
}
}
}
}
msg = iCommodityService.insert(commodity);//接口新增方法
PrintWriter out = response.getWriter();
out.write(msg);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
上面普通表单项给对象赋值我删掉了一些,字段有点多就不给大家看了都是差不多的写法,类型不同而已。还有一点大家需要注意,就是boolean类型的数据这边获取时会转成String类型,直接强转好像不行,只能用判断然后赋给定值。值拿到了剩下的就可以交给接口方法去保存了。
上一篇: php实现监听事件