java图片上传下载_java web 文件上传与下载

组件工作流程:WEB服务器request

ServletFil

eupLoad

DiskFileItem

Factory代表普通字段的FileItem代表上传文件1FileItem代表上传文件2FileItem

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

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值