java文件上传技术深入剖析

网友投稿 216 2023-07-03


java文件上传技术深入剖析

本文实例为大家分享了java文件上传技术,供大家参考,具体内容如下

表单:

客户端发送HTTP必须使用multipart/form-data数据类型,表示复合数据类型。即:

在表单中使用html标签。

需要的包:

        Commons-fileupload.jar,核心上传文件工具都在这个包中。

        commons-io.jar – 上传文件所需要的包

上传文件类详解:

DiskFileItemFactory-创建监时文件目录,指是缓存区大小

ServletFileUpload用于解析HttpServletRequest。返回一组文件对象。

FileItem – 表示用户上传的每一个文件对像。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

过渡板--了解底层

文件:


使用apache文件上传工具实现文件上传

文件:

使用apache文件上传工具实现文件上传2(解决文件名乱码)

POST1(普通表单):enctype=application/x-www-form-urlencoded(默认值)

POST2(上传文件表单):enctype=multipart/form-data:多部分(不但有文件,也有部分)

文件:

文件说明:

文件2:

文件说明2:

使用apache文件上传工具实现文件上传3(文件打散)

文件:

文件说明:

文件2:

文件说明2:

过渡板–了解底层

package cn.hncu.servlet;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class Upload0Servlet extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

InputStream in=request.getInputStream();

BufferedReader br=new BufferedReader(new InputStreamReader(in));

String line;

while((line=br.readLine())!=null){

System.out.println(line);

}

}

}

使用apache文件上传工具实现文件上传

package cn.hncu.servlet;

import java.io.File;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.List;

import java.util.UUID;

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.FileUploadException;

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

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

import org.apache.commons.io.FileUtils;

public class UploadServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.println(" ");

out.println("");

out.println("

out.println("

out.print("不支持Get方式上传。。。。。。");

out.println(" ");

out.println("");

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//在服务器上,为所有上传文件指定一个存放目录

String path=getServletContext().getRealPath("/upload");

System.out.println("path:"+path);

File dir=new File(path);

if(!dir.exists()){

dir.mkdirs();

}

//创建一个基于硬盘的工厂

//DiskFileItemFactory disk = new DiskFileItemFactory();

//设置临时目录(建议设计临时目录,否则会使用系统临时目录。)

//disk.setRepository(new File(“d:/a”));

//3、 设置向硬盘写数据的缓冲区大小

disk.setSizeThreshold(1024*4);//当文件大于此设置时,将会在临时目录下形成临时文件

//设置临时文件缓冲区大小--8K缓冲,临时文件地址

DiskFileItemFactory f=new DiskFileItemFactory(1024*8, new File("d:/a"));

//上传工具--创建用于解析的对像

ServletFileUpload upload=new ServletFileUpload(f);

upload.setFileSizeMax(1024*1024*5);//设置上传的单个文件最大为5M

//设置上传文件的最大大小,如果是多个文件,则为多个文件的和最大8M

upload.setSizeMax(1024*1024*8);//设置所有上传的文件大小之和最大为8M

//使用解析工具解析

try {

List list=upload.parseRequest(request);

for(FileItem fI:list){

System.out.println("文件内容类型:"+fI.getContentType());//文件内容类型:text/plain

System.out.println("文件名:"+fI.getName());//文件名:C:\Users\adl1\Desktop\a.txt

String ext=fI.getName().substring(fI.getName().lastIndexOf("."));//.txt

String uuid=UUID.randomUUID().toString().replace("-", "");

String fileName=uuid+ext;

// FileUtils.copyInputStreamToFile(fI.getInputStream(), new File("d:/a/d/a.txt"));//写死了

//fI.getInputStream()是真正文件信息

FileUtils.copyInputStreamToFile(fI.getInputStream(), new File(path+"/"+fileName));//写活了

}

} catch (FileUploadException e) {

e.printStackTrace();

}

}

}

在这个地方存储上传的文件

上传信息:

上传结果:

使用apache文件上传工具实现文件上传2(解决文件名乱码)

package cn.hncu.servlet;

import java.io.File;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.List;

import java.util.UUID;

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.FileUploadException;

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

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

import org.apache.commons.io.FileUtils;

public class Upload2Servlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

//如果是含上传文件的表单(POST2),该剧只能设置所上传文件的文件名中的编码(解决他的中文乱码)

//但不能解决在POST2方式下的普通表单组件的中文乱码

PrintWriter out = response.getWriter();

out.println(" ");

out.println("");

out.println("

out.println("

out.print("不支持Get方式上传。。。。。。");

out.println(" ");

out.println("");

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//第一步

//普通的form表单(POST1),下面这句可以设置普通表单组件内容的编码(能够解决它们的中文乱码问题)

request.setCharacterEncoding("utf-8");

//如果是含上传文件的表单(POST2),该句只能设置所上传文件的文件名中的编码(解决它的中文乱码)。但不能解决普通表单组件的乱码(不能设它编码)

//在服务器上,为所有上传文件指定一个存放目录

String path=getServletContext().getRealPath("/upload");

System.out.println("path:"+path);

File dir=new File(path);

if(!dir.exists()){

dir.mkdirs();

}

//设置临时文件缓冲区大小--8K缓冲,临时文件地址

DiskFileItemFactory f=new DiskFileItemFactory(1024*8, new File("d:/a"));

//上传工具

ServletFileUpload upload=new ServletFileUpload(f);

upload.setFileSizeMax(1024*1024*5);//设置上传的单个文件最大为5M

upload.setSizeMax(1024*1024*8);//设置所有上传的文件大小之和最大为8M

//使用解析工具解析

try {

List list=upload.parseRequest(request);

for(FileItem fI:list){

if((fI.isFormField())){//如果是普通表单组件:checkbox,radio,password...

// String desc=fI.getString();

System.out.println("fI.getString():"+fI.getString());

//第二步

String desc=fI.getString("utf-8");

//该句设置普通表单组件内容编码

System.out.println("编码后:"+desc);

}else{

String ext=fI.getName().substring(fI.getName().lastIndexOf("."));//.txt

String uuid=UUID.randomUUID().toString().replace("-", "");

String fileName=uuid+ext;

//fI.getInputStream()是真正文件信息

FileUtils.copyInputStreamToFile(fI.getInputStream(), new File(path+"/"+fileName));//写活了

}

}

} catch (FileUploadException e) {

e.printStackTrace();

}

}

}

上传信息:

使用apache文件上传工具实现文件上传3(文件打散)

用Hash目录优化文件存储:

Hash目录是一种优化文件存储性能的方法。无论是Windows还是linux,无论是NTFS还是ext3,每个目录下所能容纳的项目数是有限的。

并不是不能保存,而是当项目数量过大的时候,会降低文件索引速度,

所以权衡一个目录下应该保存多少文件是很必要的。保存得多了会影响性能,保存得少了会造成目录太多和空间浪费。所以当保存大批文件的时候,

需要有一种算法能将文件比较均匀地“打散”在不同的子目录下以提高每一级的索引速度,这种算法就是 Hash。通常用的MD5、sha1等都可以用来做Hash目录,我的Session里也同样使用了MD5,取得sessionID的第一位和第九位,这就构成了两级Hash路径,也就是说,系统把所有的Session文件分散到了1616=256个子目录下。假设Linux每个目录下保存1000个文件可以获得最好的空间性能比,那么系统在理想情况下可以同时有256000个session文件在被使用。

package cn.hncu.servlet;

import java.io.File;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.List;

import java.util.UUID;

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.FileUploadException;

import org.apache.commons.fileupload.ProgressListener;

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

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

import org.apache.commons.io.FileUtils;

public class Upload3Servlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

//如果是含上传文件的表单(POST2),该剧只能设置所上传文件的文件名中的编码(解决他的中文乱码)

//但不能解决在POST2方式下的普通表单组件的中文乱码

PrintWriter out = response.getWriter();

out.println(" ");

out.println("");

out.println("

out.println("

//获取GET方式的url中“?”号后面的部分

//http://localhost:8080/servletDemo3/upload?name=Jack&sex=male

String qStr = request.getQueryString();

System.out.println("qStr: "+qStr);//qStr: name=Jack&sex=male

out.print("不支持Get方式上传。。。。。。");

out.println(" ");

out.println("");

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

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

PrintWriter out = response.getWriter();

//1防黑: 防护前端采用POST1方式提交

//法1

/*

String type=request.getContentType();

if(!type.contains("multipart/form-data")){

out.println("不支持普通表单提交");

return;

}*/

//法2

boolean boo = ServletFileUpload.isMultipartContent(request);

if(!boo){

out.println("不支持普通表单提交");

return;

}

//第一步

//普通的form表单(POST1),下面这句可以设置普通表单组件内容的编码(能够解决它们的中文乱码问题)

request.setCharacterEncoding("utf-8");

//如果是含上传文件的表单(POST2),该句只能设置所上传文件的文件名中的编码(解决它的中文乱码)。但不能解决普通表单组件的乱码(不能设它编码)

//在服务器上,为所有上传文件指定一个存放目录

String path=getServletContext().getRealPath("/upload");

System.out.println("path:"+path);

File dir=new File(path);

if(!dir.exists()){

dir.mkdirs();

}

//设置临时文件缓冲区大小--8K缓冲,临时文件地址

DiskFileItemFactory f=new DiskFileItemFactory(1024*8, new File("d:/a"));

//上传工具

ServletFileUpload upload=new ServletFileUpload(f);

upload.setFileSizeMax(1024*1024*5);//设置上传的单个文件最大为5M

upload.setSizeMax(1024*1024*8);//设置所有上传的文件大小之和最大为8M

//▲4上传进度监听

upload.setProgressListener(new ProgressListener(){

private double pre=0D;

@Override//参数1:已上传多少字节 参数2:一共多少字节 参数3:第几个文件(序号从1开始)

public void update(long pByteRead, long pContentLength, int pItems) {

double d = 1.0*pByteRead/pContentLength*100;

System.out.println(d+"%");

if(pre!=d){

System.out.println(d+"%");

pre=d;

}

}

});

//使用解析工具解析

try {

List list=upload.parseRequest(request);

for(FileItem fI:list){

if((fI.isFormField())){//如果是普通表单组件:checkbox,radio,password...

// String desc=fI.getString();

System.out.println("fI.getString():"+fI.getString());

//第二步

String desc=fI.getString("utf-8");

//该句设置普通表单组件内容编码

System.out.println("编码后:"+desc);

}else{

//防护:过滤掉没选择文件的空文件组件

if(fI.getSize()<=0){

continue;//读下一个文件

}

System.out.println("文件内容类型:"+fI.getContentType());//文件内容类型:text/plain

System.out.println("文件名:"+fI.getName());//文件名:C:\Users\adl1\Desktop\a.txt

String ext=fI.getName().substring(fI.getName().lastIndexOf("."));//.txt

String uuid=UUID.randomUUID().toString().replace("-", "");

String fileName=uuid+ext;

//文件目录打散技术

String dir1=Integer.toHexString(uuid.hashCode()&0x0f);

String dir2=Integer.toHexString((uuid.hashCode()&0xf0)>>4);

//fI.getInputStream()是真正文件信息

http:// FileUtils.copyInputStreamToFile(fI.getInputStream(), new File(path+"/"+dir1+"/"+dir2+"/"+fileName));//写活了

}

}

} catch (FileUploadException e) {

e.printStackTrace();

}

}

}

打散信息:

打散结果:

文件1:

文件2:

演示上传进度原理


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java web请求和响应中出现中文乱码问题的解析
下一篇:表单input项使用label同时引用Bootstrap库导致input点击效果区增大问题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~