1.1 文件上传三要素

提供form表单,method必须是post

form表单的enctype必须是multipart/form-data

提供 input type=“file” 类型输入

1.2 实现文件上传

1.2.1 项目准备

​ 导入: commons-fileupload.jar

​ commons-io.jar

1.2.2 编写上传页面

<%@ page language="java" pageEncoding="UTF-8"%>

<!DOCTYPE HTML>

<html>

<head>

<title>文件上传</title>

</head>

<body>

<form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post">

上传用户:<input type="text" name="username"><br/>

上传文件1:<input type="file" name="file1"><br/>

上传文件2:<input type="file" name="file2"><br/>

<input type="submit" value="提交">

</form>

</body>

</html>

1.2.3 编写处理代码

package me.gacl.web.controller;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadHandleServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全

String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");

File file = new File(savePath);

//判断上传文件的保存目录是否存在

if (!file.exists() && !file.isDirectory()) {

System.out.println(savePath+"目录不存在,需要创建");

//创建目录

file.mkdir();

}

//消息提示

String message = "";

try{

//使用Apache文件上传组件处理文件上传步骤:

//1、创建一个DiskFileItemFactory工厂

DiskFileItemFactory factory = new DiskFileItemFactory();

//2、创建一个文件上传解析器

ServletFileUpload upload = new ServletFileUpload(factory);

//解决上传文件名的中文乱码

upload.setHeaderEncoding("UTF-8");

//3、判断提交上来的数据是否是上传表单的数据

if(!ServletFileUpload.isMultipartContent(request)){

//按照传统方式获取数据

return;

}

//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项

List<FileItem> list = upload.parseRequest(request);

for(FileItem item : list){

//如果fileitem中封装的是普通输入项的数据

if(item.isFormField()){

String name = item.getFieldName();

//解决普通输入项的数据的中文乱码问题

String value = item.getString("UTF-8");

//value = new String(value.getBytes("iso8859-1"),"UTF-8");

System.out.println(name + "=" + value);

}else{//如果fileitem中封装的是上传文件

//得到上传的文件名称,

String filename = item.getName();

System.out.println(filename);

if(filename==null || filename.trim().equals("")){

continue;

}

//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt

//处理获取到的上传文件的文件名的路径部分,只保留文件名部分

filename = filename.substring(filename.lastIndexOf("\\")+1);

//获取item中的上传文件的输入流

InputStream in = item.getInputStream();

//创建一个文件输出流

FileOutputStream out = new FileOutputStream(savePath + "\\" + filename);

//创建一个缓冲区

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();

message = "文件上传成功!";

}

}

}catch (Exception e) {

message= "文件上传失败!";

e.printStackTrace();

}

request.setAttribute("message",message);

request.getRequestDispatcher("/message.jsp").forward(request, response);

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

1.2.4 配置

<servlet>

<servlet-name>UploadHandleServlet</servlet-name>

<servlet-class>com.qf.web.UploadHandleServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>UploadHandleServlet</servlet-name>

<url-pattern>/servlet/UploadHandleServlet</url-pattern>

</servlet-mapping>

1.3 文件上传细节注意

上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的

1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。

3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。

4、要限制上传文件的最大值。

5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

最终处理代码改进为:

public class UploadHandleServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全

String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");

//上传时生成的临时文件保存目录

String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");

File tmpFile = new File(tempPath);

if (!tmpFile.exists()) {

//创建临时目录

tmpFile.mkdir();

}

//消息提示

String message = “”;

try{

//使用Apache文件上传组件处理文件上传步骤:

//1、创建一个DiskFileItemFactory工厂

DiskFileItemFactory factory = new DiskFileItemFactory();

//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。

factory.setSizeThreshold(1024100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB

//设置上传时生成的临时文件的保存目录

factory.setRepository(tmpFile);

//2、创建一个文件上传解析器

ServletFileUpload upload = new ServletFileUpload(factory);

//解决上传文件名的中文乱码

upload.setHeaderEncoding(“UTF-8”);

//3、判断提交上来的数据是否是上传表单的数据

if(!ServletFileUpload.isMultipartContent(request)){

//按照传统方式获取数据

return;

}

//设置上传单个文件的大小的最大值,目前是设置为10241024字节,也就是1MB

upload.setFileSizeMax(10241024);

//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB

upload.setSizeMax(10241024*10);

//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项

List list = upload.parseRequest(request);

for(FileItem item : list){

//如果fileitem中封装的是普通输入项的数据

if(item.isFormField()){

String name = item.getFieldName();

//解决普通输入项的数据的中文乱码问题

String value = item.getString(“UTF-8”);

//value = new String(value.getBytes(“iso8859-1”),“UTF-8”);

System.out.println(name + “=” + value);

}else{//如果fileitem中封装的是上传文件

//得到上传的文件名称,

String filename = item.getName();

System.out.println(filename);

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);

//如果需要限制上传的文件类型,那么可以通过MT4下载教程文件的扩展名来判断上传的文件类型是否合法

System.out.println(“上传的文件的扩展名是:”+fileExtName);

//获取item中的上传文件的输入流

InputStream in = item.getInputStream();

//得到文件保存的名称

String saveFilename = FileUploadUtils.makeFileName(filename);

//得到文件的保存目录

String realSavePath = FileUploadUtils.makePath(saveFilename, savePath);

//创建一个文件输出流

FileOutputStream out = new FileOutputStream(realSavePath + “\” + 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();

message = “文件上传成功!”;

}

}

}catch (FileUploadBase.FileSizeLimitExceededException e) {

e.printStackTrace();

request.setAttribute(“message”, “单个文件超出最大值!!!”);

request.getRequestDispatcher("/message.jsp").forward(request, response);

return;

}catch (FileUploadBase.SizeLimitExceededException e) {

e.printStackTrace();

request.setAttribute(“message”, “上传文件的总的大小超出限制的最大值!!!”);

request.getRequestDispatcher("/message.jsp").forward(request, response);

return;

}catch (Exception e) {

message= “文件上传失败!”;

e.printStackTrace();

}

request.setAttribute(“message”,message);

request.getRequestDispatcher("/message.jsp").forward(request, response);

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

//文件上传工具类

public class FileUploadUtils {

/**

* @Method: makeFileName

* @Description: 生成上传文件的文件名,文件名以:uuid+""+文件的原始名称

* @Anthor:孤傲苍狼

* @param filename 文件的原始名称

* @return uuid+""+文件的原始名称

*/

private static String makeFileName(String filename){ //2.jpg

//为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名

return UUID.randomUUID().toString() + “_” + filename;

}

/**

* 为防止一个目录下面出现太多文件,要使用hash算法打散存储

* @param filename 文件名,要根据文件名生成存储目录

* @param savePath 文件存储路径

* @return 新的存储目录

*/

private static  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

//File既可以代表文件也可以代表目录

File file = new File(dir);

//如果目录不存在

if(!file.exists()){

//创建目录

file.mkdirs();

}

return dir;

}

}

1.4 Servlet3.1支持的文件上传

package com.qf.servlet;

import java.io.IOException;

import java.util.Collection;

import javax.servlet.ServletException;

import javax.servlet.annotation.MultipartConfig;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.Part;

import org.apache.commons.io.IOUtils;

import com.qf.utils.FileUploadUtils;

/**

* Servlet implementation class UploadFileServlet2

*/

@WebServlet("/upLoadfile2")

@MultipartConfig(fileSizeThreshold=1024*100,maxFileSize=1024*1024*2,maxRequestSize=1024*1024*20)

public class UploadFileServlet2 extends HttpServlet {

private static final long serialVersionUID = 1L;

/**

* @see HttpServlet#HttpServlet()

*/

public UploadFileServlet2() {

super();

// TODO Auto-generated constructor stub

}

/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//1乱码

request.setCharacterEncoding("utf-8");

response.setContentType("text/html;charset=utf-8");

String savepath=request.getServletContext().getRealPath("/WEB-INF/upload");

File dir=new File(savepath);

if(!dir.exists()){

dir.mkdirs();

}

//2获取多分部集合

Collection<Part> parts = request.getParts();

if(parts!=null){

System.out.println("parts的个数:"+parts.size());

for (Part part : parts) {

System.out.println(part.getClass().getName());

//判断是文件还是普通项

String filename=part.getSubmittedFileName();

System.out.println(filename+"-------------");

if(filename!=null){

//文件

if(filename.trim().length()==0){

continue;

}

//获取真实的文件名:解决IE文件名的问题,兼容chrome

String dis= part.getHeader("Content-Disposition");

String realfilename=dis.substring(dis.lastIndexOf("filename=")+10,dis.length()-1);

realfilename=realfilename.substring(realfilename.lastIndexOf("\\")+1);

List<String> list= Arrays.asList(".jpg",".png",".bmp");

String ext=realfilename.substring(realfilename.lastIndexOf("."));

if(!list.contains(ext)){

response.getWriter().write("您上传的文件类型不支持");

continue;

}

//生成带uuid文件名

String uuidfilename=UpLoadUtils.createNewFileName(realfilename);

//分散存储

String newpath=UpLoadUtils.createNewPath(savepath, realfilename);

//保存文件

part.write(newpath+"/"+uuidfilename);

response.getWriter().write("上传成功:"+realfilename);

part.delete();//删除缓存文件

}else{

//普通项

String name=part.getName();

String value = request.getParameter(name);

System.out.println(name+"..."+value);

}

}

}

}

/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// TODO Auto-generated method stub

doGet(request, response);

}

}

javaWEB 之文件的上传的更多相关文章

  1. JavaWeb中文件的上传和下载

    JavaWeb中文件的上传和下载 转自: JavaWeb学习总结(五十)——文件上传和下载 - 孤傲苍狼 - 博客园https://www.cnblogs.com/xdp-gacl/p/4200090 ...

  2. Javaweb之文件的上传与下载

    Javaweb之文件的上传与下载 一.基于表单的文件上传 如果在表单中使用表单元素 <input type=“file” />,浏览器在解析表单时,会自动生成一个输入框和一个按钮,输入框可 ...

  3. JavaWeb 之文件的上传下载

    又到了每周更新博客的时候了,每看到自己发布的随笔阅读量上涨的时候就特别开心,我也会尽自己的努力提高自己的水平,总结出通俗易读的学习笔记,还望大家能多多支持!!! ------------------- ...

  4. JAVAWEB之文件的上传下载

    文件上传下载 文件上传: 本篇文章使用的文件上传的例子使用的都是原生技术,servelt+jdbc+fileupload插件,这也是笔者的习惯,当接触到某些从未接触过的东西时,总是喜欢用最原始的东西将 ...

  5. JAVAWEB之文件的上传和下载

    一.文件的上传: Enctype的属性介绍: 基于表单文件上传的界面简介: 文件上传时服务器端获取不到请求信息的原因及获取请求信息的几种方式: 输入流方式的实现: 实用工具包的实现:要导入fileup ...

  6. 小白养成记——JavaWeb之文件的上传

    文件的上传推荐使用commons的fileupload组件来完成.该组件还依赖于io包,因此需要用到两个jar包: commons-fileupload-X.X.jar commons-io-X.X. ...

  7. 【JAVAWEB学习笔记】29_文件的上传------commons-fileupload

    今天内容: 文件的上传------commons-fileupload 文件上传和下载的实质:文件的拷贝 文件上传:从本地拷贝到服务器磁盘上   客户端需要编写文件上传表单---->服务端需要编 ...

  8. JavaWeb框架_Struts2_(七)----->文件的上传和下载

    这个章节是Struts2框架应用最广泛的三个版块(上传下载.国际化.校验输入)之一,所以这一版块的学习还蛮重要的. 1. 章节目录 Struts2文件上传 单文件上传 拦截器实现文件过滤 文件上传常量 ...

  9. 文件夹上传插件webupload插件

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 先说下要求: PC端全平台支持,要求支持Windows,Mac,Linux 支持所 ...

随机推荐

  1. 转帖 java使用poi.3.10读取excel 2010

    package poi; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; ...

  2. firewall&iptables小记

    一.firewall 查看firewall状态 firewall-cmd --state 防火墙开启: 防火墙关闭: 如果firewall为关闭状态,先启动firewall systemctl sta ...

  3. Andrdoid中对应用程序的行为拦截实现方式之----从Java层进行拦截

    致谢: 感谢 简行之旅的这篇blog:http://blog.csdn.net/l173864930/article/details/38455951,这篇文章是参考这篇blog的进行一步一步操作的, ...

  4. sql 基础语法 alter用法和视图,透视

    --查询没有被删除的学生 alter table StuInfo --修改列属性 alter column isdelete bit null alter table StuInfo --删除列 dr ...

  5. cf round599 CDE

    C:结论题:设n=k*p1+r=a*p2+b,只要n有两个及以上质因子,那么必然可以用第一个质因子表示出第二个质因子,所以答案是1 反之显然是其最小质因子 /* 1 2 3 4 1 3 2 4 n的所 ...

  6. 网络-Docker 提供的几种原生网络和自定义网络(11)

    Docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络,本章重点讨论前一种 Docker 安装时会自动在 host 上创建三个网络,我们可用 docker netwo ...

  7. zju1610Count the Colors

    ZOJ Problem Set - 1610 Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting s ...

  8. Linux C遇到的常见错误

    此随笔主要记录一些Linux C遇到的常见错误,便于debug问题或自己编程时,避免发生类似的错误或问题,后续会持续更新.... 1.内存泄露问题 内存泄露是由于内存没有释放导致程序耗内存一直增大,引 ...

  9. python模块学习之HTMLTestRunner模块生成HTML测试报告

    #!/usr/bin/env python #-*- coding:utf-8 -*- from HTMLTestRunner import HTMLTestRunner import time im ...

  10. selenium自动化测试时,chrome 出现“Chrome 正受到自动测试软件的控制”的解决办法

    背景 使用selenium自动化测试的时候,启动浏览器出现'Chrome正在受到自动软件的控制'的问题,修改方法有两种. 一.在浏览器配置里加个参数,忽略掉这个警告提示语:disable_infoba ...