热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaWeb之实现文件上传与下载

1、什么是上传和下载?-数据上传是指客户端向服务器上传数据,客户端向服务器发送的所有请求都属于数据上传。文件上传是数据上传的一种特例,指的是客户端向服务器上传文件。即将保存在客户端的文

1、什么是上传和下载?

-  数据上传是指客户端向服务器上传数据,客户端向服务器发送的所有请求都属于数据上传。文件上传是数据上传的一种特例,指的是客户端向服务器上传文件。即将保存在客户端的文件上传至服务器中的一个副本,保存到服务器中。

-   数据下载是指客户端从服务器上获取数据的过程。文件下载是数据下载的一种特例,指的是客户端从服务器下载文件,即将原来保存在服务器中的文件下载到客户端中一个副本保存。通常我们对服务器所发出的请求,大多数是文件下载请求,从服务器中下载文本、图片、声音、视频等文件,然后由客户端浏览器对这些文件进行解析后,才可能看到这些多媒体信息。

-  但是我们这里所说的文件下载,指的是文件从服务器下载到浏览器后,浏览器并不直接解析,而是以附件的形式保存到客户端中。

-  上传与下载的文件可以是文本文件、图片、声音、视频等各种类型。

b8f92803d83bf1eeb80b10fbce113a91.png


2、文件上传的实现:

a、上传时对表单的要求:

-  文件上传要求客户端表单提交特殊的请求--multipart请求,即包含多部分数据的请求。所以文件上传表单对于表单数据的编码类型要求,必须为multipart/form-data。即要为标签指定enctype属性值为“multipart/form-data”。(enctype,即encodingtype,编码类型。)

-  由于客户端上传文件的大小是不确定的,所以HTTP协议规定,文件上传的数据要存放于请求正文中,而不能够出现在url的地址栏中,因为地址栏中可以存放的数据量太小。也就是说,文件上传的表单,必须提交POST请求,而不能够提交GET请求。


  enctype="multipart/form-data">
 image:
 
 


b、使用第三方工具实现文件上传:

-  需要使用到两个jar包:commons-fileupload-1.3.3.jar和commons-io-2.6.jar,jar包可以在apache官网中下载(commons-fileupload-1.3.3.jar依赖于commons-io-2.6.jar,如果只使用fileupload jar包,会运行程序时会抛出异常)

-  示例代码如下:

-  在index.jsp文件中填写的代码如下所示:

<%@ page language="java" cOntentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ page import="com.geeklicreed.listeners.Student"%>  name: image:  


- 为web应用添加一个Servlet,在web.xml文件中添加配置信息:

elfileUploadServletcom.geeklicreed.servlet.FileUploadServletfileUploadServlet/fileUpload


-  自定义serlvet类,在doPost方法中编写简单实现文件上传的代码:

package com.geeklicreed.servlet;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;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.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;public class FileUploadServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    protected void doPost(HttpServletRequest request, HttpServletResponse response)             throws ServletException, IOException {        //判断请求是否为multipart请求        if(!ServletFileUpload.isMultipartContent(request)){            throw new RuntimeException("当前请求不支持文件上传");        }        try {            //创建一个FileItem工厂            DiskFileItemFactory factory = new DiskFileItemFactory();            //创建文件上传核心组件            ServletFileUpload servletFileUpload = new ServletFileUpload(factory);            //解析请求,获取到所有的item            List items = servletFileUpload.parseRequest(request);            //遍历items            for(FileItem item : items){                if(item.isFormField()){  //若item为普通表单项                    String fieldName = item.getFieldName();  //获取表单项名称                    String fieldValue = item.getString();  //获取表单项的值                    System.out.println(fieldName + " = " + fieldValue);                }else{  //若item为文件表单项                    //获取上传文件原始名称                    String fileName = item.getName();                       //获取输入流,其中有上传 文件的内容                    InputStream is = item.getInputStream();                    //获取文件保存在服务器的路径                    String path = this.getServletContext().getRealPath("/images");                    //创建目标文件,将用来保存上传文件                    File file = new File(path, fileName);                    //将输入流中的数据写入到输出流中                    OutputStream os = new FileOutputStream(file);                    //将输入流中的数据写入输出流中                    int len = -1;                    byte[] buf = new byte[1024];                    while((len = is.read(buf)) != -1){                        os.write(buf, 0, len);                    }                                        os.close();                    is.close();                }            }        } catch (FileUploadException e) {            e.printStackTrace();        }    }}


-  启动web应用,访问index.jsp,添加图片后,点击“上传”,可以发现控制台打印结果,在工作空间web项目的指定目录可以看到图片已经上传:(在Eclipse中,默认会把Web项目放到Eclipse的工作空间下的.metadata\.plugins\org.eclipse.wst.server.core\tmp0(或者是tmp1)\wtpwebapps\下)

b21e32099f0c94dbd9f2c5ce326a994f.png

729ee6601f720fb6fd4c181782ac64b3.png

314014bfe306dd1b3104d4a0c3cccff5.png



-  FileUploadServlet类中的代码相关解释:(也包含使用fileupload jar包文件上传时的常用方法)

-  org.apache.commons.fileupload.disk.DiskFileItemFactory类:默认的FileItemFactory实现类。这个实现创建FileItem实例(文件条目)。如果是小条目,会将其存入内存中,如果是大条目,会将其存入硬盘中的临时文件。大小条目数据的临界值,是可配置的。

The default FileItemFactory implementation. This implementation creates FileItem instances which keep their content either in memory, for smaller items, or in a temporary file on disk, for larger items. The size threshold, above which content will be stored on disk, is configurable, as is the directory in which temporary files will be created.


-  setRepository(File repository)方法:设置临时存储文件(这个文件大小大于指定配置临界值)存放的目录位置。

-  setSizeThreshold(int sizeThreshold)方法:设置临界值(单位为字节),当超过这个值时文件将会直接写入硬盘中。(如sizeThreshold为1024 * 1024,则为1兆)

void setRepository(File repository)

Sets the directory used to temporarily store files that are larger than the configured size threshold.

void setSizeThreshold(int sizeThreshold)

Sets the size threshold beyond which files are written directly to disk.


-  org.apache.commons.fileupload.servlet.ServletFileUpload类:处理文件上传的高级API。(如何存储各个部分的数据是由创建它们的工厂决定;给定的部分可能在内存中、磁盘上或者其他地方)

High level API for processing file uploads.This class handles multiple files per single HTML widget, sent using multipart/mixed encoding type, as specified by RFC 1867.  Use parseRequest(HttpServletRequest) to acquire a list of FileItems associated with a given HTML widget.How the data for individual parts is stored is determined by the factory used to create them; a given part may be in memory, on disk, or somewhere else.


-  parseRequest方法:解析请求,获取FileItem类型元素的List对象:

List parseRequest(HttpServletRequest request)

Processes an RFC 1867 compliant multipart/form-data stream.


-  ServletFileUpload类的父类org.apache.commons.fileupload.FileUploadBase的方法:

-  设置每个item的头部字符编码,其可以解决文件名的中文乱码问题:(若tomcat版本较低时,可能会出现文件名中文乱码)

void setHeaderEncoding(String encoding)

Specifies the character encoding to be used when reading the headers of individual part.


-  setFileSizeMax(long fileSizeMax)方法设置单个上传文件允许上传的最大边界值。

-  setSizeMax(long sizeMax)方法设置一次上传所有文件的总和最大边界值。(单位都为字节)

void setFileSizeMax(long fileSizeMax)

Sets the maximum allowed size of a single uploaded file, as opposed to getSizeMax().

void setSizeMax(long sizeMax)

Sets the maximum allowed size of a complete request, as opposed to setFileSizeMax(long).


-  isMultipartContent(HttpServletRequest req)方法:判断该请求是否包含multipart内容

static boolean isMultipartContent(HttpServletRequest req)

Deprecated. 

1.1 Use the method on ServletFileUpload instead.


-  org.apache.commons.fileupload.FileItem接口:表示在multipart/form-data的POST请求中内的一个文件或者表单条目。

This class represents a file or form item that was received within a multipart/form-data POST request.


-  isFormField方法:判断FileItem实例是否为一个普通form项:

boolean isFormField()

Determines whether or not a FileItem instance represents a simple form field.


-  getFieldName方法:获取对应文件条目(即单个表单项)的name属性值:

String getFieldName()

Returns the name of the field in the multipart form corresponding to this file item.


-  getName方法:获取客户端文件系统中的原上传文件名:(包含后缀名)

String getName()

Returns the original filename in the client's filesystem, as provided by the browser (or other client software).


-  getInputStream方法:获取输入流,用于取出上传文件中的内容:

InputStream getInputStream()

Returns an InputStream that can be used to retrieve the contents of the file.


-  delete方法:删除任何相关联的临时磁盘文件:

void delete()

Deletes the underlying storage for a file item, including deleting any associated temporary disk file.


3、文件下载的实现:

a、超链接下载:将下载资源作为超链接的链接目标文件出现。若浏览器可以解析该资源文件,则将在浏览器上直接显示文件内容;若浏览器不支持该文件的解析,则会弹出另存为对话框,要求用户保存。

-  该下载方式的缺点很明显,不同的浏览器,以及相同的浏览器所安装的插件不同,那么其对于资源的解析能力也就不同,其是否弹出另存为对话框的情况也就不一样。决定权由浏览器掌握。

-  如在jsp文件中添加如下代码,在ff浏览器中点击,直接在浏览器中打开该图片:

timg.jpg


b、Servlet方式的文件下载:

-  示例代码:

-  jsp文件中的内容和web.xml文件中添加的配置:

download image
            downloadServlet        com.geeklicreed.servlet.DownloadServlet                downloadServlet        /download    


-  自定义Servlet类中添加如下代码:

package com.geeklicreed.servlet;import java.io.IOException;import java.io.InputStream;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class DownloadServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    protected void doGet(HttpServletRequest request,            HttpServletResponse response) throws ServletException, IOException {        String fileName = "火拳艾斯.jpg";        byte[] bytes = fileName.getBytes("utf-8");        fileName = new String(bytes, "ISO8859-1");        //修改响应的头部属性content-disposition值为attachment        response.setHeader("content-disposition", "attachment;filename=" + fileName );        //获取连接服务器端资源文件的输入流        InputStream is = this.getServletContext().getResourceAsStream("/images/timg.jpg");        //获取输出流        ServletOutputStream os = response.getOutputStream();        //将输入流中的数据写入到输出流中        int len = -1;        byte[] buf = new byte[1024];        while((len = is.read(buf)) != -1){            os.write(buf, 0 , len);        }                os.close();    }}


-  如果想要浏览器下载的方式是以附件的形式下载,需要修改响应的头部属性content-disposition值为attachment;filename=文件名 + 后缀名。(filename表示以附件形式下载显示的文件名)

javax.servlet.ServletContext接口的getResourceAsStream方法:获取web应用中的指定路径下的资源,以字节输入流InputStream的形式返回。

 java.io.InputStream getResourceAsStream(java.lang.String path)
Returns the resource located at the named path as an InputStream object.


c、启动web应用,点击超链接后,可以看到文件以附件的形式下载:

e4f78ad2d6a233bc7e5460214d89d0b8.png


4、附加说明:

-  上传文件目录的管理:当用户上传的文件过多,而单个目录能够存放的文件个数有限,(windows系统下单文件夹中最大可有65,534个文件)所以需要上传的文件有时需要分目录进行管理。

-   可以使用java.io.File类的mkdir()方法来在当前目录中创建直接子目录,或者使用mkdirs()方法创建当前目录的多层子目录:

boolean mkdir()

Creates the directory named by this abstract pathname.

boolean mkdirs()

Creates the directory named by this abstract pathname, including any necessary but nonexistent 

本文出自 “12392717” 博客,请务必保留此出处http://12402717.blog.51cto.com/12392717/1977293


推荐阅读
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 20211101CleverTap参与度和分析工具功能平台学习/实践
    1.应用场景主要用于学习CleverTap的使用,该平台主要用于客户保留与参与平台.为客户提供价值.这里接触到的原因,是目前公司用到该平台的服务~2.学习操作 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • php支持中文文件名
    2019独角兽企业重金招聘Python工程师标准大家可能遇到过上传中文文件名的文件,或者读取中文目录时不能读取,出现错误的情况这种情况是因为php自动将中文字符转成了utf8 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 小程序自动授权和手动接入的方式及操作步骤
    本文介绍了小程序支持的两种接入方式:自动授权和手动接入,并详细说明了它们的操作步骤。同时还介绍了如何在两种方式之间切换,以及手动接入后如何下载代码包和提交审核。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 阿里云虚拟主机安装多个织梦系统的方法
    本文介绍了在阿里云虚拟主机上安装多个织梦系统的方法。通过创建不同名称的文件夹并将不同的域名解析到对应的目录,可以实现多个系统的安装。在安装过程中需要注意修改数据库前缀,并在系统设置中还原数据库。同时还介绍了阿里云虚拟主机二级域名绑定二级目录和域名重定向的用法。 ... [详细]
author-avatar
keleisibuo
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有