实现WEB
开发中的文件上传功能,需完成如下二步操作:
一、在WEB
页面中添加上传输入项,<input type=“life”
name=“”>
,使用时注意:
1.
必须要设置input
输入项的name
属性,否则浏览器将不会发送上传文件的数据。
2.
必须把input
项的enctype
属值设为multipart/form-data.
设置该值后,浏览器
二、在上传文件时,将把文件数据附带在http
请求消息体中,并使用MIME协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理。
#
如何在Servlet中读取文件上传数据,并保存到服务器本地硬盘中?
Request
对象提供了一个getInputStream()
方法,使用这个方法可以获取浏览器提交过来的输入流。但如果浏览器上传多个文件时,我们应该如何区分开来?这是一项复杂的工作。
为了方便用户处理文件上传数据,Apache
开源组织提供了用于处理上面应用的开源组件——Commons-fileupload
。这个组件使用简单,性
能也比较优异,所以几乎都使用它来实现上传文件的处理功能。Struts
的上传文件处理部分也是使用它实现的。
#Fileupload
组件工作流程:
WEB
服务器
request
ServletFil
eupLoad
DiskFileItem
Factory
代表普通字段的
FileItem
代表上传文件1
FileItem
代表上传文件2
FileItem
isFileForm
getFieldName
getString
getInputStream
getName
getInputStream
getName
核心API-DiskFileItemFactory
:
DiskFileItemFactory
是创建FileItem
对象的工厂,这个工厂常用方法:
1.
public DiskFileItemFactory(int sizeThreshold, java.io.File
repository)
,常用的构造函数。
2.
public void setSizeThreshold(int
sizeThreshold)
,设置内存缓冲区的大小,默认值为10K
。当上传文件大于缓冲区大小时, fileupload
组件将使用临时文件缓存上传文件。
3.
public void setRepository(java.io.File
repository)
,指定临时文件目录,默认值为System.getProperty("java.io.tmpdir")
。
核心API-ServletFileupLoad:
ServletFileUpload
负责处理上传的文件数据,并将表单中每个输入项封装到一个FileItem
对象中。常用方法有:
1.
boolean isMultipartContent(HttpServletRequest
request)
,判断上传表单是否为上传表单类型。
2.
List parseRequest(HttpServletRequest
request)
,解析request
对象,并把表单中的每一个输入项包装到一个fileItem
对象中,并返回一个保存了所有FileItem
的list
集合。
3.
setFileSizeMax(long
fileSizeMax)
,设置上传文件的最大尺寸值。
4.
setSizeMax(long sizeMax)
,设置上传文件总量的最大值。
5.
setHeaderEncoding(java.lang.String
encoding)
,设置编码格式。如果文件路径中存在中文可能会造成文件路径乱码,用此方法处理可以解决。
6.
setProgressListener(ProgressListener
pListener)
,设置进程监听器,与AWT
和Swing
的事件处理机制一样。文件上传一点就会触发ProgressListener
,这样我们就可以获取文件上传的进度。
#
上传文件案例:
public class FileuploadServlet extends HttpServlet {
public void
doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
//
创建文件处理工厂,它用于生成FileItem
对象。
DiskFileItemFactory difactory = new DiskFileItemFactory();
//
设置缓存大小,如果上传文件超过缓存大小,将使用临时目录做为缓存。
difactory.setSizeThreshold(1024 * 1024);
//
设置处理工厂缓存的临时目录,此目录下的文件需要手动删除。
String dir = this.getServletContext().getRealPath("/");
File filedir = new File(dir + "filetemp");
if (!filedir.exists())
filedir.mkdir();
difactory.setRepository(filedir);
//
设置文件实际保存的目录
String userdir = dir + "files";
File fudir = new File(userdir);
if (!fudir.exists())
fudir.mkdir();
//
创建request
的解析器,它会将数据封装到FileItem
对象中。
ServletFileUpload sfu = new ServletFileUpload(difactory);
//
解析保存在request
中的数据并返回list
集合
List list = null;
try {
list = sfu.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
//
遍历list
集合,取出每一个输入项的FileItem
对象,并分别获取数据
for (Iterator it = list.iterator(); it.hasNext();) {
FileItem fi = (FileItem) it.next();
if (fi.isFormField()) {
System.out.println(fi.getFieldName());
System.out.println(fi.getString());
} else {
//
由于客户端向服务器发送的文件是客户端的全路径,在这我们只需要文件名即可
String filename = fi.getName();
int index = filename.lastIndexOf("\\");
if(index != -1)
filename = filename.substring(index+1);
//
向服务器写出文件
InputStream in = fi.getInputStream();
FileOutputStream fos = new FileOutputStream(fudir + "/"
+filename);
byte[] buf = new byte[1024];
int len = -1;
while((len = in.read(buf)) != -1){
fos.write(buf, 0, len);
}
//
关闭流
if(in != null){
try{
in.close();
}finally{
if(fos!=null)
fos.close();
}
}
}
}
}
public void
doPost(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
doGet(request, response);
}
}
上面的代码只是功能的练习,实际开发中的文件上传需要考虑诸多因素,我们接下来继续学习。
#JS
动态添加文件上传框和按钮的JavaScript代码:
function add(){
var file = document.create_rElement_x("input");
file.type = "file";
file.name = "file";
var butt = document.create_rElement_x("input");
butt.type = "button";
butt.value = "
删除";
butt.onclick = function rem(){
//
必须使用按钮的父节点DIV
的父节点来删除自己和自己的父节点DIV
。
this.parentNode.parentNode.removeChild(this.parentNode);
};
var div = document.create_rElement_x("div");
div.a(file);
div.a(butt);
var parent = document.getElementByIdx_x_x("files");
parent.a(div);
}
#上传文件的处理细节(1):
1.
中文文件乱码的问题,
可以调用两个方法来设置字符编码:servletUpLoader.setHeaderEncoding()
或request.setCharacterEncoding()
。我们可以在源文件的创建ServletFileUpload
对象后边添加如下代码:
sfu.setHeaderEncoding("UTF-8");
2.
临时文件的删除,如果临时文件大于setSizeThreshold
设置的缓存大小,Commons-fileupload
组件将使用 setRepository
设置的临时目录来保存上传的文件,上传完成后我们需要手动调用FileItem.delete
来删除临时文件。建议不要修改缓
存区大小,如果设置缓存为1MB
,1000
个用户上传文件就需要1000MB
内存,服务器会受不了的。我们删除掉setSizeThreshold
的代
码,并在每次完成一个文件后添加下而的代码:
//
删除临时目录中的文件
fi.delete();
#上传文件的处理细节(2):
1.
在上面的代码中,我们将文件的实际保存目录设置在WEB-INF
目录之外。这样外部可以直接访问被上传的文件,这会造成安全问题。比如用户上传了一个带有
恶意脚本功能的JSP
文件,然后从外部访问执行了JSP
文件…
后果不堪设想。所以我们将源代码中对应位置处修改如下:
//
之所以放在"WEB-INF"
目录下是为了防止上传的文件被直接被访问的安全问题
String userdir = dir + "WEB-INF/files";
2.
一个WEB
应用会许多不同的用户访问,不同的用户可能会上传相同名称的文件,如果这样可能会造成文件覆盖的情况发生,所以我们必须保证文件名称的唯一性,我编写一个方法来生成唯一性名称的文件名:
private
String uuidName(String fileName){
UUID uuid = UUID.randomUUID();
return uuid.toString() + "_" + fileName;
}
我们将代码“filename =
filename.substring(index + 1);”
修改为:filename = uuidName(filename.substring(index +
1))
3.
如果一个目录下的文件过多,会极大减慢文件的访问速度。比如一个目录下的文件如果超过1000
个,达到1
万个呢?恐怖!我们必须编写一个目录结构生成算法,来分散存上传的文件。我们一个方法:
private
String hashPath(String dir, String fileName) {
int hashCode = fileName.hashCode();
int dir1 = (hashCode >> 4)
& 0xf;
int dir2 = hashCode & 0xf;
String newpath = dir + "/" + dir1 + "/" + dir2 + "/";
File file = new File(newpath);
if(!file.exists()){
file.mkdirs();
}
return newpath + uuidName(fileName);
}
上传文件的处理细节(3)
1.
使用ProgressListener
显示上传文件进度,在创建ServletFileUpload
之后添加如下代码:
//
设置文件上传进度监听器
sfu.setProgressListener(new ProgressListener() {
public void update(long pBytesRead, long pContentLength, int
pItems) {
System.out.println("
已上传:" + pBytesRead + "
总大小:"
+ pContentLength);
}
});
2.
上面的代码会造成频繁的打印,为了使它在上传一定数量后再打印,比如上传10KB
后再打印,我们修改上面的代码如下:
//
设置文件上传进度监听器
sfu.setProgressListener(new ProgressListener() {
long temp = -1;
public void update(long pBytesRead, long pContentLength, int
pItems) {
long size = pBytesRead / 1024 * 1024 * 10;
if(temp == size)
return;
temp = size;
if(pBytesRead != -1)
System.out.println("
已上传:" + pBytesRead + "
总大小:"
+ pContentLength);
else
System.out.println("
上传完成!");
}
});
上面的代码比较经典,好好回味一下。
#文件下载:
WEB
应用中实现文件下载的两种方式:
1.
超链接直接指向下载资源
2.
程序实现下载需设置两个响应头:
(1).
设置Content-Type
的值为:application/x-msdownload
。Web
服务器需要告诉浏览器其所输出的内容的类型不是普通的文本文件或
HTML
文件,而是一个要保存到本地的下载文件。
(2). Web
服务器希望浏览器不直接处理相应的实体内容,而是由用户选择将相应的实体内容保存到一个文件中,这需要设置 Content-Disposition
报头。该报头指定了接收程序处理数据内容的方式,在 HTTP
应用中只有 attachment
是标准方式,attachment
表示要求用户干预。在 attachment
后面还可以指定 filename
参数,该参数是服务器建议浏览器将实体内容保存到文件中的文件名称。在设置
Content-Dispostion
之前一定要指定 Content-Type
。
为实现文件下载,首先我们遍历目录下所有文件,Servlet
:
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ListFileServlet extends HttpServlet {
public void
doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
//
获取目录
String dir =
this.getServletContext().getRealPath("/WEB-INF/files");
HashMap map = new HashMap();
listFile(new File(dir), map);
//
将文件列表设置到request
的属性中,然后由JSP
页面打印列表。
request.setAttribute("filemap", map);
request.getRequestDispatcher("/list.jsp").forward(request,
response);
}
private void
listFile(File f, HashMap map) {
if (f.isFile()) {
String path = f.getAbsolutePath().substring(
this.getServletContext().getRealPath("/").length());
String name = f.getName();
name =
name.substring(name.indexOf("_")+1);
//BASE64Encoder encoder = new BASE64Encoder();
map.put(path, name);
} else {
File[] files = f.listFiles();
for (int i = 0; i < files.length; i++) {
listFile(files[i], map);
}
}
}
public void
doPost(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
doGet(request, response);
}
分享到:
相关推荐
这个"Java Web 文件上传与下载 jar包"提供了一组关键的库文件,可以帮助开发者轻松实现这些功能。以下是这四个jar文件的主要内容及其在文件处理中的作用: 1. **standard.jar**:这是Java Servlet API的一部分,...
在Java Web开发中,文件上传、下载和查看是常见的功能需求,尤其在构建交互性强的Web应用程序时。这里我们将深入探讨这些操作的核心概念和技术。 **文件上传** 文件上传主要是指用户通过Web表单将本地文件传输到...
Java Web 文件操作是日常开发解决的问题,主要是针对解决文件的上传下载、查看操作。下面是相关的知识点: 一、Java Web 文件上传操作 * 文件上传是指通过 HTTP 请求将文件从客户端上传到服务器端的过程。在 Java ...
### Java Web 文件上传与下载详解 #### 一、概述 在Java Web开发中,文件的上传与下载是一项常见的功能需求。本文将详细解析如何利用Java Web技术栈中的Servlet结合JavaScript来实现文件的上传与下载功能。我们将...
本教程将深入探讨如何使用Java实现Web文件上传和下载的程序,这对于初学者理解Web开发的基本流程非常有帮助。 一、文件上传 1. **Multipart请求**:在HTTP协议中,文件上传通常涉及Multipart/form-data类型的请求...
在Java Web开发中,文件上传和下载是常见的功能需求,主要涉及到Servlet技术。Servlet是Java Servlet API提供的一个接口,...通过深入理解并实践这些步骤,开发者可以熟练地在Java Web应用中实现文件的上传与下载功能。
在Java Web开发中,文件上传、下载和查看是常见的功能需求,尤其对于构建交互性强的Web应用程序至关重要。这里我们将深入探讨这些操作的核心概念和技术。 首先,让我们从文件上传开始。在Java Web中,文件上传主要...
当你新建一个Java Web项目后,可以直接将这两个目录内的文件复制并覆盖到你的项目中,以便快速开始使用提供的上传下载功能。 总结,`FileUtils`是Apache Commons IO库的一个强大工具,能够简化Java Web应用中的文件...
java web 开发 上传文件至服务端保存于服务端某个文件夹下 java代码示例
在Java Web开发中,文件的上传和下载是常见的功能需求,尤其在构建动态网站或Web应用程序时。本项目采用jsp(JavaServer Pages)和servlet技术来实现这一功能。下面将详细阐述这两种技术以及如何结合它们来处理文件...
综上所述,Java Web文件上传涉及到的技术栈广泛,包括后端的Servlet API、文件处理库,前端的表单设计,以及中间的服务器配置和安全策略。通过这些技术,开发者可以构建出安全、高效的文件上传系统。
在Java Web开发中,文件上传是一项常见的功能,而为用户提供实时的上传进度条可以显著提升用户体验。本项目提供的"java web 文件上传进度条源码"着重解决了这一需求,包括已用时间、剩余时间、上传速度以及进度条的...
在描述中提到的“测试可用的,网上下了很多都不能用,经过自己的努力成功了”,这可能指的是开发者在寻找和实践Java Web文件上传解决方案时遇到了问题,但最终找到了一个可行的实现方法。现在,我们将深入探讨这个...
文件上传在JAVA WEB开发中是一项基础且重要的功能,它允许用户通过Web界面上传本地文件到服务器。本案例基于Struts框架实现,Struts是Apache软件基金会的一个开源项目,主要用于构建MVC(Model-View-Controller)...
在Java开发中,文件上传和下载是常见的功能需求,尤其在Web应用中,例如用户上传个人照片、下载文档等。Struts2是一个流行的Java Web框架,它提供了方便的文件上传和下载支持。以下是对这个主题的详细讲解。 一、...
首先,我们来看看“JspSmart文件上传下载包”,这是一个专门为Java Web设计的轻量级组件,用于处理文件上传和下载的场景。 1. **文件上传**: - **Servlet API**:在Java Web中,文件上传主要依赖于Servlet API中...
### Java Web 文件的上传与下载 #### 12.1 文件上传原理 文件上传是许多Web应用程序中的常见功能。从用户界面来看,文件上传过程似乎很简单:用户选择一个或多个文件,然后通过表单提交到服务器。然而,在后台,这...
在Java开发中,文件和图片的上传下载是常见的功能需求,尤其在Web应用中更为重要。本篇文章将详细探讨三种不同的实现方式,分别是使用JSP+Servlet、SmartUpload库以及Apache的FileUpload组件。 首先,我们来看第一...
在Java编程中,多文件上传和下载是常见的功能,尤其在Web应用中。这个主题涉及到几个关键知识点,包括Servlet、Multipart请求解析、文件处理以及安全性。以下是对这些概念的详细解释: 1. **Servlet**: Servlet是...