1.本质:I/O读写
客户端(浏览器)发送文件 Http协议
文件的内容写出去 客户端本地输入流(内容) 网络输出流
服务器(Web容器)接受文件 协议
文件的内容读过来 网络输入流(内容) 服务器本地输出流
2.可以使用别人写好的包来进行文件的上传和下载
常用的是apache组织提供的一个包
commons-fileupload.jar http://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi
commons-io.jar https://commons.apache.org/proper/commons-io/download_io.cgi
3.上传的步骤
浏览器端
①写一个jsp/html做展示(选择某一个文件)
②必须通过表单提交
③必须使用post
规定:ServletFileUpLoad类中一个属性 post
字节数:
get没有限制,肯定通过URL拼串
不同浏览器对于URL处理长度有所不同
post没有限制,需要web容器的支持,跟容器的处理性能有关
④以前我们使用表单时只有两个属性 action method
如果想要做文件上传,表单中必须添加一个属性 enctype=”multipart/form-data”
⑤必须使用,通过这个组件让用户选择上传的文件
不仅仅能得到文件名,文件内容也会读出来
服务器端
①引入文件上传需要的jar包
commons-fileupload-1.4.jar
commons-io-2.6.jar
②使用一个DiskFileItemFactory对象,使用一个ServletFileUpload对象,使用upload对象解析request,得到一个List<FileItem>集合
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//创建一个工厂
DiskFileItemFactory factory=new DiskFileItemFactory();
ServletFileUpload upload=new ServletFileUpload(factory);
//通过upload解析request对象,因为请求携带的信息都在request对象中
List<FileItem> itemList= upload.parseRequest(req);
}catch (Exception e){
e.printStackTrace();
}
}
③自己的业务逻辑
(我们用桌面充当浏览器端,D://Test充当服务器端)
for(FileItem item:itemList){
if(item.isFormField()){//是一个普通的组件
//注意不能使用request.getParameter("key");来获取
String key=item.getFieldName();//获取组件的name属性
//String value=item.getString();获取组件的value属性
String value=item.getString("UTF-8");//使用重载传递字符集处理字符问题
System.out.println(key+"---"+value);
}else{//是file文件
String key=item.getFieldName();//获取组件的name属性
String realFileName=item.getName();//获取上传文件的真实名字
//如果传递的文件的真实名字中出现中文乱码问题,req.setCharacterEncoding("UTF-8");可以解决
//我们用桌面充当浏览器端,D://Test充当服务器端
item.write(new File("D://Test/"+realFileName));
// InputStream is= item.getInputStream();//获取一个输入流,读取网络传递过来的文件内容
//原生的方式实现文件的上传
// OutputStream outputStream = new FileOutputStream("D://test/"+realFileName);
// byte[] b = new byte[1024];
// int length = inputStream.read(b);
// while(length!=-1){
// outputStream.write(b,0,length);
// outputStream.flush();
// length = inputStream.read(b);
// }
// outputStream.close();
}
}
如果上传的文件比较大
产生临时文件,为了防止丢包
默认情况下临时文件存在Tomcat的temp文件夹中
factory.setSizeThreshold(int);设置缓冲区大小,默认为10240
factory.setRepository(new File(“路径”));设置缓冲区位置
还可以设置上传文件本身大小:
upload.setFileSizeMax(long);单个上传文件的大小
upload.setSizeMax(long);上传文件的总大小
文件上传时如果放在一个固定的位置,可移植性不好,一般放在当前工程的根目录下
String path=this.getServletContext().getRealPath(“/“);获取根目录
如果文件上传出现文件名冲突的问题?
原来名字+用户+时间.原来后缀
1_zzt_date.jpg
用一个随机产生的名字当做保存在服务器中的文件名
1.jpg—->xxxxx.jpg 1 xxxxx 路径 用户 上传时间
一个随机名字创建一个文件夹
1.jpg放在文件夹里 用户 路径 文件夹名
有些时候可能上传的文件需要控制类型
自己设计一个方法
private boolean testFileType(String fileName){
String[] box = {"txt","doc","pdf","jpg","png"};
for(int i=0;i<box.length;i++){
if(fileName.endsWith(box[i])){
return true;
}
}
return false;
}
补充:
有时上传时我们需要监督进度,可以通过upload对象来实现
upload.setProgressListener(new ProgressListener() {
@Override
public void update(long l, long l1, int i) {
//l表示已经上传的字节数(每4096个字节就会更新)
//l1表示上传文件的总字节数
//i表示正在上传第几个组件
}
});