JavaWeb-News-文件上传
来源:互联网 发布:外国人对淘宝的评价 编辑:程序博客网 时间:2024/05/16 18:57
话说:
昨天把分页作为礼物送给了自己,今天文件上传和昨天的一气呵成。
昨天的新闻没有上传功能,今天总结下;整体修改还是建立在上一篇分页基础之上。
目标:文件上传
围绕4个问题:
Q1:如何自定义文件名?
Q2: 如何获取文件后缀名?
Q3:如何获取文件存储路径(Web服务器和工程目录下各一份)?
Q4:如何将文件路径要存储到数据库表中的pic字段中?
前期准备:
1)在数据库里面新建一列pic,因为反射机制不能默认为null,所以通通把这一列设置为”images/default.jpg”;
存图片的列需要设置成BLOB、MEDIUMBLOB或LONGBLOB等数据类型
但是一般我们肯定不直接在数据库存图片楼,节省速度。
所以,我们存放图片路径。
update t_news set pic= “images/default.jpg”;
2)为了保证发布新闻界面newsAdd.jsp页面在提交表单的时候,可以提交文件,所以要新增表单属性:enctype=”multipart/form-data”;同时在newsServlet中新增注解:@MultipartConfig。这样就保证了页面添加文件时候,Servlet可以顺利接收到。
newsAdd.jsp
<%-- Created by IntelliJ IDEA. User: Meice Date: 2017/10/1 Time: 15:02 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>发布新闻</title></head><body> <form action="news.do" method="post" enctype="multipart/form-data"> <%--传递参数的时候,可以直接传参,也可以用隐藏域--%> <input type="hidden" name="op" value="add"/> <table> <tr> <td>标题</td> <td><input type="text" name="title"></td> </tr> <tr> <td>作者</td> <td><input type="text" name="author"></td> </tr> <tr> <td>封面</td> <td><input type="file" name="pic" alt="尚未提交文件"></td> </tr> <tr> <td colspan="2"><input type="submit" value="发布"></td> </tr> </table> </form></body></html>
以上新增了封面这一行,结果是这样的:
好!准备工作到此结束,正式开始搞定4个问题。
Q1:如何自定义文件名?
为避免用户上传文件名相同,所以我们要按照自己规则来重命名文件,类似QQ截图那样。
同样,我们也作为一个工具类,封装成方法getFileName()
public static String getFileName(String suffix) { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String now = sdf.format(new Date()); return "news"+now+suffix;}
效果是这样的:news20171015171838.png;这样也就搞定了文件前缀名。
//获取文件File;但是用户上传的文件如何获取呢?
Part part = req.getPart("pic"); part.write("F:\\enheng.exe");String header = part.getHeader("content-disposition");
part是个接口,通过part的getHeader()方法可以获取的一个key-value的一串名字:类似下面这样:form-data; name=”pic”; filename=”02_BaseDao再设计.exe”
我们需要的是filename,所以通过截取获得后缀名。(前办部分我们按照时间戳自定义,避免用户传入文件名称相同)
Q2:如何获取文件后缀名?
前面header就是一个包含文件完整名称的key-value键值队,截取出后缀名即可。为便于后面运用,我们封装为一个方法getSuffix()
//定义获取文件后缀的方法getSuffix()private String getSuffix(String filename){ //详细过程看main()方法测试 String subStr = filename.substring(filename.indexOf("filename"),filename.lastIndexOf("\"")); subStr = subStr.substring(subStr.indexOf("\"")+1); subStr = subStr.substring(subStr.indexOf(".")); return subStr;}
这样,不论你传输什么文件,后缀名都可以搞定了。jpg,jpeg,gif都可以,视频也可以的,只不过,页面不好显示。
Q3:如何获取文件存储路径(Web服务器和工程目录下各一份)?
为什么要获取绝对路径呢?因为不同浏览器有的支持绝对路径,有的不支持。
要是再Linux中就好了。
项目路径,直接可以查看,我们定义为proPath
项目在Tomcat服务器部署路径,通过getRealPath()方法可以获取,定义为realPath
String proPath ="D:\\Users\\Administrator\\IdeaProjects\\Meice_idea_utimate\\JavaWeb_Servlet_Paging\\web\\images";//获取项目在服务器部署后的真实路径;服务器也会迁移啊。Linux就不用了在部署Web服务器对应Images目录下再次写入一次String realPath = req.getSession().getServletContext().getRealPath("images");
Q4:如何将文件路径要存储到数据库表中的pic字段中?
//相对路径用于存储表中pic字段String filename = FileUploadUtil.getFileName(getSuffix(header));String relPath = "images/"+ filename; //写入到项目文件中 part.write(proPath+"/"+filename);.....news.setPic(relPath);
同时,我们只需要稍作修改这几个地方,整个图片上传就搞定啦!
1、news.setPic(relPath); 为pic字段设置属性,路径就是images/我们自定义的文件名。一旦用户点击上传,项目路径下会按照我们的命名规则产生新的文件:类似这样:news20171015205739.jpg
项目一旦部署,会在工程对应的Web服务器端再次生成这个文件。
2、修改newsUpdate2()方法,创建对象的时候,新增pic属性即可
//法2:封装发布新闻的方法(前后对比明显吧!)public int newsAdd2(News news){ String sql = "insert into t_news (title,author,pic) values (?,?,?)"; Object[] params = {news.getTitle(),news.getAuthor(),news.getPic()}; return CUD(sql,params);}
3、最后,在显示页面newsShow.jsp,显示图片。
<td align="center"><img src="${news.pic}" width="60px" height="60px"></td>
4、调试过程,可能报一下错误:
这个时候,我在部署后的路径下找到了上传的图片;但是在工程images下面没有找到。
奇怪的是,这里报错是从C:根目录下开始找的……;
这里是正常的,在IDEA里面,就是会自己在生成一个路径。经过排查,发现不能同时给两个位置写入文件。
//写入到项目文件中 part.write(proPath+"/"+filename);//写入到Tomcat服务器中 // part.write(realPath+"/"+filename);
只有写入项目中,然后重新部署,刷新就可以显示啦!
以下是完整代码:
主要修改的就是newsServlet、我们自己定义的工具类FileUploadUitl(重命名文件)和getSuffix()方法(获取文件后缀名)
实体类News
package com.hmc.jdbc.news.model;public class News { private int id; private String title; private String author; private String pic; public News() { } public News(int id, String title, String author) { this.id = id; this.title = title; this.author = author; } public News(int id, String title, String author, String pic) { this.id = id; this.title = title; this.author = author; this.pic = pic; } //没有2个参数的构造方法,我自己就造一个出来;因为增加新闻不需要考虑ID,对于客户来说。 public News(String title, String author) { this.title = title; this.author = author; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getPic() { return pic; } public void setPic(String pic) { this.pic = pic; } @Override public String toString() { return "News{" + "id=" + id + ", title='" + title + '\'' + ", author='" + author + '\'' + ", pic='" + pic + '\'' + '}'; }}
以上仅仅增加了pic这个属性,生成了set(),get()方法。
NewsServlet
package com.hmc.jdbc.news.servlet;import com.hmc.jdbc.news.dao.BaseDao;import com.hmc.jdbc.news.dao.NewsDao;import com.hmc.jdbc.news.model.News;import com.hmc.jdbc.news.model.Pager;import com.hmc.jdbc.news.util.FileUploadUtil;import com.hmc.jdbc.news.util.StringConvertUtil;import javax.servlet.ServletException;import javax.servlet.annotation.MultipartConfig;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.Part;import java.io.IOException;import java.sql.Connection;import java.util.List;/** * User:Meice * 2017/10/5 */@WebServlet(urlPatterns = "/news.do")@MultipartConfigpublic class NewsServlet extends BaseServlet { NewsDao nd = new NewsDao(); BaseDao bd = new BaseDao(); //查(R) // 未避免代码混乱,把显示新闻列表封装成方法;这里采用最高级的显示新闻方法listShow3() private void list (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String sql = "select * from t_news"; List<News> list =(List<News>) bd.listShow3(sql,News.class,null); //3 存储到req中 req.setAttribute("list", list); req.getRequestDispatcher("newsShow.jsp").forward(req, resp); } //定义查询分页显示页面的方法pageList() private void pageList(HttpServletRequest req,HttpServletResponse resp ) { //接收参数pageIndex String strPageIndex = req.getParameter("pageIndex"); String strPageSize = req.getParameter("pageSize"); int pageIndex = StringConvertUtil.getVal(strPageIndex); int pageSize = StringConvertUtil.getVal(strPageSize); //当时转换方法里面如果为null返回的是0 pageIndex = pageIndex ==0?1:pageIndex; pageSize = pageSize == 0?5:pageSize; Pager<News> pager = new Pager<>(); //避免最后页会多出来 pager.setCount(nd.count()); pager.setPageIndex(pageIndex); pager.setPageSize(pageSize); //调用pageList()方法 pager = nd.pageList(pager); //存储到req中 req.setAttribute("pager",pager); //页面跳转 try { req.getRequestDispatcher("newsShow.jsp").forward(req,resp); } catch (ServletException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //增(C) private void add(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException { //接受参数 String title = req.getParameter("title"); String author = req.getParameter("author"); //获取文件File Part part = req.getPart("pic"); //获取part头信息 String header = part.getHeader("content-disposition"); //这个路径是我们项目的images所在路径;在本项目路径下写入一次 String proPath ="D:\\Users\\Administrator\\IdeaProjects\\Meice_idea_utimate\\JavaWeb_Servlet_Paging\\web\\images"; //获取项目在服务器部署后的真实路径;服务器也会迁移啊。Linux就不用了在部署Web服务器对应Images目录下再次写入一次 String realPath = req.getSession().getServletContext().getRealPath("images"); //D:\Users\Administrator\IdeaProjects\Meice_idea_utimate\out\artifacts\JavaWeb_Servlet_Paging_war_exploded\images //相对路径用于存储表中pic字段 String filename = FileUploadUtil.getFileName(getSuffix(header)); String relPath = "images/"+ filename; //写入到项目文件中 part.write(proPath+"/"+filename); //写入到Tomcat服务器中 // part.write(realPath+"/"+filename); News news = new News(title,author); news.setPic(relPath); int result = nd.newsAdd2(news);//(写这些方法从后往前写) if(result > 0) { req.getRequestDispatcher("news.do?op=pageList").forward(req,resp); }else { req.getRequestDispatcher("newsAdd.jsp").forward(req,resp); } } //定义获取文件后缀的方法getSuffix() private String getSuffix(String filename){ //详细过程看main()方法测试 String subStr = filename.substring(filename.indexOf("filename"),filename.lastIndexOf("\"")); subStr = subStr.substring(subStr.indexOf("\"")+1); subStr = subStr.substring(subStr.indexOf(".")); return subStr; } //改(U) //显示要修改的新闻 public void changeShow(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException { //接受参数 String strId = req.getParameter("id"); int id = StringConvertUtil.getVal(strId); News news = nd.newsPut3(id); req.setAttribute("news",news); req.getRequestDispatcher("newsUpdate.jsp").forward(req,resp); } //执行修改操作 public void change(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException { //接受参数 String strId = req.getParameter("id"); int id = StringConvertUtil.getVal(strId); String title = req.getParameter("title"); String author = req.getParameter("author"); News news = new News(id,title,author); //调用方法 int result = nd.newsUpdate2(news); if(result >0) { req.getRequestDispatcher("news.do?op=pageList").forward(req,resp); }else { req.getRequestDispatcher("newsUpdate.jsp").forward(req,resp); } } //删(D) private void del(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException { //接受参数 String strId = req.getParameter("id"); int id = StringConvertUtil.getVal(strId); int result = nd.newsDel2(id); req.getRequestDispatcher("news.do?op=pageList").forward(req,resp); } public static void main(String[] args) { //form-data; name="pic"; filename="02_BaseDao再设计.exe" String str = "form-data; name=\"pic\"; filename=\"02_BaseDao再设计.exe\""; System.out.println(str.substring(str.indexOf("filename"),str.lastIndexOf("\""))); String subStr = str.substring(str.indexOf("filename"),str.lastIndexOf("\"")); //filename="02_BaseDao再设计.exe subStr = subStr.substring(subStr.indexOf("\"")+1); System.out.println(subStr); //"02_BaseDao再设计.exe 02_BaseDao再设计.exe subStr = subStr.substring(subStr.indexOf(".")); System.out.println(subStr); //截取过程如下 /* filename="02_BaseDao再设计.exe 02_BaseDao再设计.exe .exe */ }}
FileUpLoad()工具类
package com.hmc.jdbc.news.util;import java.text.SimpleDateFormat;import java.util.Date;/** * User:Meice * 2017/10/15 */public class FileUploadUtil { public static String getFileName(String suffix) { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String now = sdf.format(new Date()); return "news"+now+suffix; } public static void main(String [] args) { System.out.println(getFileName(".png")); }}
newsShow.jsp
<%@ page import="java.util.List" %><%@ page import="java.util.Enumeration" %><%@ page import="com.hmc.jdbc.news.model.News" %><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%-- Created by IntelliJ IDEA. User: Meice Date: 2017/10/1 Time: 13:30 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><%--如果不用jstl,还是采用JSP嵌套获取--%><%--<% //本来在页面,我们获取list集合非常简单,${}这样就获取了,但是实际过程中,我们在JSP代码中没发做到用这个来获取 List<News> list =(List<News>) request.getAttribute("list");%>--%><html><head> <title>Meice的新闻列表</title></head><body> <h2 align="center">Meice的新闻列表</h2><br/> <a href="newsAdd.jsp">发布新闻</a> <table border="1" align="center" width="80%"> <thead> <tr> <th>编号</th> <th>标题</th> <th>作者</th> <th>图片</th> <th>操作</th> </tr> </thead> <tbody> <%--${news}--%> <%--这里传过来就是那幅图的场景;现在的问题是我不知道怎么接收这个传递过来的值,直接用EL取出来的是 个List<News>的集合。这边又没法遍历。?? 如果不用JSTL,我们用普通的for each,问题是怎么取出这个值。 --%> <c:forEach var="news" items="${pager.datas}"> <tr> <td align="center">${news.id}</td> <td align="center">${news.title}</td> <td align="center">${news.author}</td> <td align="center"><img src="${news.pic}" width="60px" height="60px"></td> <td align="center"> <a href="news.do?op=changeShow&id=${news.id}">修改</a> <a href="news.do?op=del&id=${news.id}" onclick="return confirm('真的忍心删我?')">删除</a> </td> </tr> </c:forEach> <tr> <td colspan="5" align="center"> <div style="float: left;margin-left: 150px"> <c:if test="${pager.pageIndex>1}"> <a href="news.do?op=pageList&pageIndex=1">首页</a> <a href="news.do?op=pageList&pageIndex=${pager.pageIndex-1}">上一页</a> </c:if> <c:forEach var="pn" begin="${pager.start}" end="${pager.end}"> <c:if test="${pn==pager.pageIndex}"> ${pn} </c:if> <c:if test="${pn != pager.pageIndex}"> <a href="news.do?op=pageList&pageIndex=${pn}">${pn}</a> </c:if> </c:forEach> <%--EL表达式支持运算--%> <c:if test="${pager.pageIndex<pager.totalPage}"> <a href="news.do?op=pageList&pageIndex=${pager.pageIndex+1}">下一页</a> <a href="news.do?op=pageList&pageIndex=${pager.totalPage}">末页</a> ${pager.pageIndex}/${pager.totalPage} </c:if> </div> <%--以下实现页面跳转--%> <form action="news.do?op=pageList" method="post" style="float:right;margin-right: 200px" > <input type="text" name="pageIndex" style="width: 30px;height: 30px" value="${param.pageIndex}" /> <select name="pageSize" style="height: 30px"> <option value="5" ${param.pageSize==5?'selected':''}>5</option> <option value="10" ${param.pageSize==10?'selected':''}>10</option> <option value="20" ${param.pageSize==20?'selected':''}>20</option> </select> <input type="submit" value="Go"style="float: right;height: 30px"> </form> </td> </tr> </tbody> <tfoot></tfoot> </table></body></html>
其他代码都和上一篇博客一样。
最终效果图:
总结:
主要就是解决文章开头的3个问题。顺着问题找解决方案,目的就很明确。
1、实体类News中封装一个存放图片的属性pic即可,调用方式和其他属性类似;
2、通过request的getPart()方法,返回一个part对象,调用getHeader()方法,根据需要截取文件后缀和重命名文件;
3、part.write()方法可以把我们命名好的文件,存入到工程目录和服务器目录下;
4、把命名好的文件名赋值给变量relPath,传递到页面;
5、修改对应的newsUpdate2()方法,页面newsShow.jsp做对应修改即可。
好了,各位读者,下期见!晚安!
- JavaWeb-News-文件上传
- JavaWeb之文件上传
- javaweb文件上传
- JavaWeb之文件上传
- javaweb文件上传原理
- javaweb文件上传
- javaweb文件上传
- javaweb文件的上传
- JavaWeb之文件上传
- JavaWeb 文件上传
- JavaWeb文件上传
- JavaWeb文件上传
- javaWeb 文件上传功能
- JavaWeb常用文件上传
- 上传文件(javaWeb)
- JavaWeb 文件 上传 下载
- javaweb---上传文件
- JavaWeb文件上传、下载
- 数据结构
- 《现代操作系统》第一章 引论
- [POJ 1144] Network Tarjan算法求割点
- Android修改状态栏颜色详解
- 332. Reconstruct Itinerary
- JavaWeb-News-文件上传
- 在 nginx 中部署 angular 应用
- 机器学习实战—笔记-kNN算法
- oracle 12c GI安装配置共享存储分区
- 二叉树遍历
- Mybatis的分页插件
- Python csv文件读取(表格文件)
- Android 6.0 权限简单介绍
- Freeswitch监听功能--单向监听