图片上传之fileupload

最近学习了图片上传这个功能,这个功能比较常见,因此来整理一下,了解上传的基本原理,以便后期遇到图片上传功能可以很快上手。

要说图片上传,我们先来说一下图片上传后存储的两种方式:一种是将图片存储到数据库中;一种是将图片存储在服务器文件目录中。首先,对于将图片存储到数据库中适合数据量小的情况,因为写到数据库的图片需要转换成二进制流的格式,占用数据空间比较,适合少量图片的存储,比如,系统中某些小图标,写到数据库中的优点是比较安全,不容易被用户不小心删除。但是,图片 存在数据库的操作方面的局限性太大, 还要拼凑sql ,db server还要parse sql, write into file, 读写性能不高,备份越来越大。 如果是大量的图片存储通常的做法是保存到服务器的某个目录下。一方面 ,其 完成图片上传有很多方式,可以采用流的方式,可以采用ftp 的方式等;另一方面备份方便(只备DB ),读取高性能。这种方式便于直接访问,适用于直接显示方面的需求,但路径与图片的映射容易出问题 。对于超级大型应用, 需要的是数据库的批量查询和返回结果,这时应用分布式将图片存储在数据库中,比如 谷歌的Bigtable ,也可以理解成nosql,以及Amazon的S3存储服务是基于文档型数据库的,也是nosql 。现在很多网站直接把自己的二进制数据放在S3 ,能够满足全球分布式管理,并且不用自己动手。想说一句,看应用的规模,以及扩展性的需要,选择适合的图片存储方式,没有绝对的答案。

      下面我将以图片存储在服务器目录中的形式,介绍一下fileupload 方式的图片上传。common-fileupload组件是apache的一个开源项目之一,可以从 http://jakarta.apache.org/commons/fileupload/ 下载。该组件简单易用,可实现一次上传一个或多个文件,并可限制文件大小。

下面我就讲一下基本实现:

       首先需要在lib 目录下引入:commons-io-1.3.2.jar和 commons-fileupload-1.3.1.jar 。

前端代码:

<span style="font-size:14px;"><%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<html>  
  <head>
  
    <title>fileUpload</title>
    
    <meta http-equiv="Content-Type" content="text/html; charset=GB18030">

  </head>

  <body>
  
   <form action="./servlet/FileUploadServlet" method="post" enctype="multipart/form-data" name="form1">
   
     <input type="file" name="file">
     
     <input type="submit" name="Submit" value="upload">
     
   </form>
   
   <form action="./servlet/HelloWord" method="post">
   
    <input type="submit"/>
    
   </form>
   
    <form name="uploadform" method="POST" action="./servlet/FileUploadServlet" ENCTYPE="multipart/form-data">

        <table border="1" width="450" cellpadding="4" cellspacing="2" bordercolor="#9BD7FF">

        <tr><td width="100%" colspan="2">

                        文件1:<input name="x" size="40" type="file">

        </td></tr>

        <tr><td width="100%" colspan="2">

                        文件2:<input name="y" size="40" type="file">

        </td></tr>

        <tr><td width="100%" colspan="2">

                        文件3:<input name="z" size="40" type="file">

        </td></tr>

        </table>

        <br/><br/>

        <table>

        <tr><td align="center"><input name="upload" type="submit" value="开始上传"/></td></tr>

       </table>
       
     </form>

  </body>
</html>
</span>

      注意:文件上传在前端要 使用file标签 ,采用form表单提交 enctype=" multipart/form-data "   。 关于enctype="multipart/form-data" 的说明: 在jsp 中使用了该格式,对应的Servlet就不能使用request.getParameter()取得参数,要使用ServletFileUpload对象的parseRequest方法先把request对象中的数据解析,然后,使用解析出的元素的isFormField标志,配合getFieldName方法来获取数据。

java代码:

<span style="font-size:14px;">package uploadPack;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@SuppressWarnings("serial")
public class FileUploadServlet extends HttpServlet {
   //存储图片到数据库类的方法
   ItemManager itemManager  = new  ItemManagerImpl() ; 
   //用于存放上传文件
   private File uploadPath;
   //用于存放临时文件的目录
   private File tempPath;
   @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
     doPost(req, resp);
  }
  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    //从test_upload.jsp中拿取数据,因为上传页的编码格式跟一般的不同,使用的是enctype="multipart/form-data"
    //form提交采用multipart/form-data,无法采用req.getParameter()取得数据
    //DiskFileItemFactory:创建FileItem对象的工厂,这个工厂类中可以配置内存缓冲池大小和临时文件的目录
     DiskFileItemFactory factory = new DiskFileItemFactory();
    // maximum size that will be stored in memory
     factory.setSizeThreshold(4096);
    // the location for saving data that is larger than getSizeThreshold()
     factory.setRepository(tempPath);
     //ServletFileUpload:负责处理上传的文件数据,并将每部分的数据封装成到FileItem对象中
     //在接收上传文件数据时,会将内容保存到内存缓存区中,如果文件内容超过了 DiskFileItemFactory 指定的缓冲区的大小,   
         //那么文件将被保存到磁盘上,存储为DiskFileItemFactory指定目录中的临时文件
     //等文件数据都接收完毕后,ServletFileUpload再从文件中将数据写入到上传文件目录下的文件中
     ServletFileUpload upload = new ServletFileUpload(factory);
    // maximum size before a FileUploadException will be thrown   
     upload.setSizeMax(1000000* 100);
     try {
       //从test_upload.jsp中拿取数据,因为上传页的编码格式跟一般的不同,使用的是enctype="multipart/form-data"
       //form提交采用multipart/form-data,无法采用req.getParameter()取得数据
       List fileItems =upload.parseRequest(req);
       //循环提交的表单
       for (Iterator iter = fileItems.iterator(); iter.hasNext();) {
         FileItem item = (FileItem) iter.next();
         String itemNo = "";  
          //判断是文件还是文本信息   
                //是普通的表单输入域   
                if(item.isFormField()) {  
  if ("itemNo".equals(item.getFieldName())) {  
    //将FileItem对象中保存的主体内容作为一个字符串返回,乱码可以加编码方式
      itemNo = item.getString();  
  }  
                }  
                 //是否为input="type"输入域
         if(!item.isFormField()){
          //上传文件的名称和完整路径 
            String name =item.getName();
            long size =item.getSize();
          //判断是否选择了文件
            if ((name ==null || name.equals("")) && size==0) {
            continue;
          }
            //截取字符串 
  name = name.substring(name.lastIndexOf("\\") + 1, name.length());
  //将文件保存到目录下,不修改文件名   
  item.write(new File(uploadPath, name));  
  //将图片文件名写入打数据库	 
  itemManager.uploadItemImage(itemNo, name);  
         }
      }
       resp.sendRedirect(req.getContextPath() + "/servlet/item/SearchItemServlet");  
    } catch (Exception e) {
      e.printStackTrace();
      throw new ApplicationException("上传失败!");  
    }
  }
      /**
       * 在系统启动的时候就初始化,在初始化时,检查上传图片的文件夹和存放临时文件的文件夹,如果不存在就创建
       */
      @Override  
      public void init() throws ServletException {  
        //获取根目录对应的真实物理路径   
          uploadPath = new File(getServletContext().getRealPath("/upload"));  
          //如果目录不存在   
          if (!uploadPath.exists()) {  
              //创建目录   
              uploadPath.mkdir();  
          }  
          //临时目录   
          //File tempFile = new File(item.getName())构造临时对象   
          tempPath = new File(getServletContext().getRealPath("/temp"));  
          if (!tempPath.exists()) {  
              tempPath.mkdir();  
          }  
   }
}
</span>

配置文件:

<span style="font-size:14px;"><?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
  xmlns="http://java.sun.com/xml/ns/j2ee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <servlet>
    <servlet-name>FileUploadServlet</servlet-name>
    <servlet-class>uploadPack.FileUploadServlet</servlet-class>
    <load-on-startup>10</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>FileUploadServlet</servlet-name>
    <url-pattern>/servlet/FileUploadServlet</url-pattern>
  </servlet-mapping>
</web-app>
</span>
前面的是转载lvshihua的,博客地址,写的很好忍不住就复制了,实现的是单个文件的上传,发现List fileItems =upload.parseRequest(req)返回的是list那么如果上传时多个文件,应该也是同样处理。下面我补充下j2ee下载压缩文件包的方法
<pre name="code" class="java">public String downloadZIP() {
		try {
			//定义压缩包的名字
			String ZIP_NAME = "downloadZIP.zip";
			//多文件名
			String downloadFile[] = this.getRequest().getParameterValues(
					"checkname");
			//多文件路径
			String[] filePath = this.getRequest().getParameterValues("url");
			//设置返回消息头
			this.getResponse().setHeader(
					"Content-Disposition",
					"attachment;fileName="
							+ URLEncoder.encode(ZIP_NAME, "UTF-8"));


			ZipOutputStream out = new ZipOutputStream(this.getResponse()
					.getOutputStream(), Charset.forName("utf-8"));// Need
			// JDK_7
			for (int i = 0, length = downloadFile.length; i < length; i++) {
				File download = new File(filePath[i]);
				FileInputStream fis = new FileInputStream(download);
				ZipEntry entry = new ZipEntry(download.getName());
				out.putNextEntry(entry);
				this.io(fis, out, 10240);
				out.closeEntry();
				fis.close();
			}
			out.flush();
			out.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}




 



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值