文件上传原理

        文件上传在很多网站应用中是必不可少的,在 电子商务中上传商品图片,在音乐网站中上传流行 歌曲......一个高效率的文件上传功能尤为重要。 笔 者主要介绍用jsp 方式实现的两个 代码简短又高效率的文件上传功能。

        在此基础上,可以对文件上传功能进行进一步的完善,如限制上 传文件的大小, 格式, 指定存放路径,结合数据库 对上传后的文件进行有效的管理等等。在 B/S 模式中,文件上传到服务器的操作分 为:request, 打开request 中的输入流, 生成文件 输出流对象,提取request中上传文件的数据等。

(1)算法设计

在 B/S 模式中, 浏览器  与服务器 是请求 和响应 的 关系。获取来自浏览器端的数据, 主要是通过对 request 进行处理。 文件上传必须使用 post 方式进行数据提交, 文件数据和请求的头部信息被封装在 request中, 被请求执行的服务器端程序通过各种方法对 request 的信息进行处理后, 再执行关键的 I/O 操作。流程图如下:

 

java图片写入上传 javaee上传图片_java图片写入上传

 

(2)JSP实现文件上传原理

利用 JSP 内置对象 request 的 getInputStream()方法生成 ServletInputStream类的对象, 即 I/O 中的 输入流对象。

 ServletInputStream类提供了 public int readLine(byte[] b,int off,int len) throws java.io.IOException 方法, 该方法按行读取数据, 返回值是实际读取的字节数,request 对象调用 public  int  getContentLength()返回的请求的字节数,这个值比上传文件的实际大 小要稍大, 因为其中包含了一些附加信息, 比如文 件类型, 文件路径和文件名等,这些附加信息一般 在 200个字节左右, 在限制上传文件大小的时候可以 充分利用该方法。

 

对输入流中的数据按行读取,不难发现前四行 数据 (上传单个文件时) 正好是附加的信息,例如上传一个静态网页文件,前四行数据如下:

java图片写入上传 javaee上传图片_java图片写入上传_02

 第一行是“boundary”  表示数据开始。第二 行是对数据内容的描述,表单中 file控件的名称以及所上传文件的路径和文件名。第三行是文件类 型。 第四行为一空行。 从第二行数据中取出文件扩 展名后,可以进行上传文件类型的控制, 如上传图 片则判断扩展名是否为.jpg 或.gif 等格式。 需要注意的是, 如果取出的文件路径和文件名值为 空字符串,说明用户没有选择上传的文件,这时候 要进行相应的处理,避免出错。

同时也能看出最后一行也是“boundary” 表 示数据结束。

所上传文件的实际数据从第五行开始,持续到 倒数第二行。 根据这样的特点, 用 ServletInputStream 类的  public int readLine(byte[] b,int off,int len)方法 实现上传功能远远要比使用从InputStream类继承 得到的read(byte[]b) 简单。 从第二行读取文件 名, 这个文件名可作为服务器端保存文件时的文件名。

保存文件的操作通过 FileOutStream 类的 write() 方法实现。在创建该类的对象时, 根据实 际情况指定文件的保存路径。write()方法有多个 型构, 具体选择哪个也很重要。 上传文件一定要保 持文件的大小不改变, 一是要对写进文件的字节数 进行控制!,即实际读取多少数据则写入多少。二要 剔除 request中附加的信息。 因此本方法中使用  write()方法, 文件保存成功后要关闭相应的I/O 流对象, 释放占用的资源。

 

(3)经典示例

步骤一:静态页面部分(index.jsp)用于选择需要进行 上传的文件

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>请选择上传的文件</title>
</head>
<body >
<form action="upload.jsp" method="post" enctype="multipart/form-data">
<input type="file" name="select" />
<input type="submit" value="上传"/>
</form>
</body>
</html>

步骤二:编辑处理上传页面(upload.jsp)

<%@page import="java.io.FileOutputStream"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
ServletInputStream in = request.getInputStream();
int len = request.getContentLength();
byte[] b = new byte[len];
int i=0;
i=in.readLine(b,0,b.length);
len-=i;
i=in.readLine(b,0,b.length);
len-=i;
String s = new String(b,0,i);
String fileName = s.substring(s.lastIndexOf("=")+2,s.lastIndexOf("\""));
if("".equals(fileName)){
out.print("<script>alert('请选择文件上传');location.href='index.jsp'</script>");
}else{
String saveName = fileName.substring(fileName.lastIndexOf("\\")+1);
i=in.readLine(b,0,b.length);
len-=i;
i=in.readLine(b,0,b.length);
len-=i;
FileOutputStream fos = new FileOutputStream(request.getRealPath("")+"/"+saveName);
while((i=in.read(b,0, 128))!=-1&&len>47){
len-=i;
fos.write(b,0,i);
}
in.close();
fos.close();
out.print("<script>alert('文件上传成功!');location.href='index.jsp'</script>");
}
%>