您的位置:首页 > 编程语言 > Java开发

使用原生的Servlet封装文件上传和下载

2018-01-10 15:01 471 查看
原生的东西在任何地方都是适用的,就算是以后引用在框架中,也可以使用原生的东西;

新手对于文件的上传和下载没有头绪的可以作为参考:

以一个图片上传,下载和展示为例:

一:首先是一个选择上传文件的input控件

<form
action="${thispath }/UAD?method=up&upload=upload&before=/imi&id=${user.id }"
method="post" enctype="multipart/form-data">
选择上传的图片:<input type="file" name="photo" /> <input id="is_admin"
type="hidden" value="${user.id == adminuser.id ? 1 : 2}" /> <input
type="submit" value="上 传" />

</form>


看拼接的地址"${thispath }/UAD?method=up&upload=upload&before=/imi&id=${user.id
}",明显地址指向了一个类,名为UAD,还关联到了一个类imi.这里UAD就是封装的上传下载类.imi则是指执行完成上传操作之后跳转的地址.

二:贴出来UAD类的代码

package com.love.servlet;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.URLEncoder;

import java.util.List;

import java.util.UUID;

import javax.servlet.ServletContext;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

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

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

/**

 * Uploading And Downloading For Image--上传和下载图片

 * 

 * @author 愤青Diana

 * @使用时要传递信息

 * @1-upload:上传图片要保存在服务器的文件夹名称

 * @2-method:up(上传)或者down(下载)

 * @3-form表单中file-input:file-input框的name值为photo

 * @4-before,后加目标地址:上传成功后会返回到一个目标地址

 * @5-filename,可以直接用request获取:跳转地址后会同时转发一个添加图片的名称

 * @6-filename=xxxx.jpg:下载业务需要提供要下载的图片的名称

 * @7-upload值:下载业务需要提供要下载的图片所在浏览器的目标文件夹

 * @8-id值:上传业务时可以附带一个id值(亦可不加),id为标志性参数,不作任何处理,直接传递到下一个页面

 */

@WebServlet("/UAD")

public class UAD extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* 重写service方法
*/
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String method = request.getParameter("method");
if ("up".equals(method)) {
this.Uploading(request, response);
} else if ("down".equals(method)) {
this.Downloading(request, response);
} else {
System.out.println("没有匹配的方法!");
}
}

/**
* 下载方法

* @param request
* @param response
* @throws IOException
*/
private void Downloading(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("下载服务启动------");
// 获取图片在服务器的文件夹名称
String upload = request.getParameter("upload");
String fileName = request.getParameter("filename");
// 消息头
response.setContentType("application/octet-stream");// 流响应给浏览器
// 添加一个消息头 保存 另存为 交互 下载文件是中文要用URLEncoder.encoder();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
// 获取文件在服务器上的位置
// Servlet ========ServletContext========服务器
ServletContext app = getServletContext();
String downloadPath = app.getRealPath(upload + File.separator + fileName);
File f = new File(downloadPath);
// 文件复制
InputStream in = new FileInputStream(f);
OutputStream out = response.getOutputStream();
// jar包中自带的工具
CopyUtils.copy(in, out);
System.out.println("yes");
}

/**
* 上传方法

* @param request
* @param response
* @throws IOException
* @throws ServletException
*/
private void Uploading(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("上传服务启动------");
// 获取一个标志性的id,不作处理,直接传递到下一个页面
int id = 0;
if (request.getParameter("id") != null) {
id = Integer.parseInt(request.getParameter("id"));
System.out.println("UAD中拿到的id为:" + id);
}
// 获取图片在服务器的文件夹名称
String upload = request.getParameter("upload");
// 上传完成后要跳转的目标地址
String before = request.getParameter("before");
String filename = "";// 定义一个生成的文件名
// 获取文件--方式:磁盘文件工厂
// 包名为:org.apache.commons.
FileItemFactory fif = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(fif);
// 解析request:FileItem 一个input框就是一个文件条目
try {
// 获取所有的input框
List<FileItem> parseRequest = sfu.parseRequest(request);
for (FileItem fi : parseRequest) {
// 判断是否是上传组件
if (fi.isFormField()) {
// 返回true即为普通组件
} else {
// 上传组件
// 获取服务器路径
ServletContext app = request.getSession().getServletContext();
// 打开服务器某个路径
String realPath = app.getRealPath(upload);
// 获取文件名称--目的是为了获取后缀
String finame = fi.getName();
// 截取后缀--subString截取字符串--lastIndexOf,从最后一个""开始
String suffix = finame.substring(finame.lastIndexOf("."));
// 使用UUID类为文件重命名
String newname = UUID.randomUUID().toString();
// 拼接文件名称,代表separator//或\\
String name = realPath + File.separator + newname + suffix;

filename = newname + suffix;// 获取生成的文件名
File f = new File(name);// 根据文件名生成文件
// 严谨性判断
if (!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
// 写入文件
fi.write(f);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
request.setAttribute("filename", filename);
// request.setAttribute("id", id);
System.out.println("yes");
/* response.sendRedirect(request.getContextPath()+"/down.jsp"); */
request.getRequestDispatcher(before + "?id=" + id).forward(request, response);
}

}


在UAD方法的介绍中已经把这个类所需要的一些属性和这些属性分别代表的是什么意思解释的很清楚了.这个类返回的属性也写的十分清除,返回到request中的数据可以在imi类中直接获取,imi类可以替换为自己定义的任何一个类或者jsp页面.下面再贴出一个imi类的Demo;

三:imi类代码

package com.love.servlet;

import java.io.IOException;

import java.sql.Timestamp;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.love.model.Imgs;

import com.love.model.User;

import com.love.service.UserService;

import com.love.service.UserServiceImpl;

/**

 * 接收上传的数据查询并显示

 */

@WebServlet("/imi")

public class imi extends HttpServlet {
UserService us = new UserServiceImpl();


@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("imi.service()");
int id = Integer.parseInt(request.getParameter("id"));
String filename = (String) request.getAttribute("filename");
User user = us.findId(id);
int userid = 0;
if (user != null) {
userid = user.getId();
Imgs im = new Imgs(filename, new Timestamp(System.currentTimeMillis()), userid);
System.out.println("im----" + im);
us.addImgs(im);
request.setAttribute("user", user);
}
request.getRequestDispatcher("/AdmintistionServlet?method=about").forward(request, response);
}

}


贴出来的imi类也比较简单,就是把上传好的文件记录下来,把文件名和文件路径存到数据库中,然后跳转到下一个执行操作的地方.当然了,这只是一个同步的上传和下载操作,属于一种链式操作,这样操作如果文件过大的话就会导致用户等待时间过长,减低用户体验.我们一般都会用异步的方式处理文件的上传操作.在执行ajax异步操作时,只需要在imi类中执行完存储等操作之后不执行页面跳转,而是执行ajax的异步回调就可以了,原理是一样的,就是发起方法和结束为止不同而已,核心的UAD上传下载是不变得.

四:下载地址拼接

愤青Diana

<a href="${thispath}/UAD?method=down&upload=upload&filename=${namelist.imgname }">下载</a>


下载操作并不需要拼接下载之后的跳转链接,因为一般执行下载操作之后就开始在浏览器端下载文件了.无需做页面的跳转工作,就算是需要跳转也可以直接在页面执行a标签点击同步执行操作;

愤青Diana
第一次写文章,多多批评,多多指教!

WeChat:jy271613/QQ:2757525270

愤青Diana
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息