文件上传

1. 文件上传功能的实现

上传和下载Web应用开发需求中出现频率较高的词汇。在JSP应用开发过程中,编写“文件上传”功能代码主要有三种方式:

  • 采用自编写的JavaBean组件
  • 采用JspSmart公司自己编写的JspSmartUnload组件
  • 采用O’Reilly公司的Cos组件

1.1 采用自编写的JavaBean组件

  • 要编写一个实现文件上传功能的组件,首先需要先了解数据传输的原理,根据数据处理的规律来完成相关的编码。步骤为:

    1.获取上传数据的规律。案列如下:

1
2
<!--如果要实现文件上传功能 需要添加 enctype="MULTIPART/FORM-DATA"-->
<form enctype="MULTIPART/FORM-DATA"></form>
1
2
//js版给form添加属性,实现文件上传
form.encding="multipart/form-data"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!--index.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上载</title>
</head>
<body>
<form action="up.jsp" enctype="multipart/form-data" method="post">
作者: <input type="text" name="author"><br>
公司: <input type="text" name="company"><br>
选择要上传的文件 <input type="file" name="filename"><br>
<input type="submit" value="上载">
</form>
</body>
</html>
<!--up.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:useBean id="TheBean" scope="page" class="org.xmh.demo.UploadBean" />
<%
TheBean.doUpload(request);
%>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.xmh.demo;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class UploadBean {
public void doUpload(HttpServletRequest request) throws IOException {
PrintWriter pw=new PrintWriter(new BufferedWriter(new FileWriter("d:\\xmh.txt")));
ServletInputStream in=request.getInputStream();
int i=in.read();
while(i!=-1){
pw.print((char)i);
i=in.read();
}
pw.close();
}
}
  1. 编写上传组件。
    • 根据上文所述,如果想要获取表单提取的数据,需要设计一个功能类来处理相关的数据信息。下面设计了一个FileUploadBean.java的类,他就是自定义处理上传功能的类。
  2. 使用自编写的上传组件。
    • 案例2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自编写上传组件--文件上传示例</title>
</head>
<body>
<form action="selfBean.jsp" enctype="multipart/form-data" method="post">
作者:<input type="text" name="author"><br>
公司:<input type="text" name="company"><br>
说明: <textarea name="comment" ></textarea><br>
选择要上载的文件: <input type=file name="filename"><br>
文件描述: <input type="text" name="description"><br>
<input type="submit" value="Upload">
</form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:useBean id="TheBean" class="org.xmh.demo.FileUploadBean" scope="page">
<%
TheBean.setSavePath("d:/");
TheBean.doUpload(request);

out.println("Filename:"+TheBean.getFilename());
out.println("<BR>内容类型:"+TheBean.getContentType());
out.println("<BR>作者:"+TheBean.getFieldValue("author"));
out.println("<BR>公司:"+TheBean.getFieldValue("company"));
out.println("<BR>说明:"+TheBean.getFieldValue("comment"));
%>
</jsp:useBean>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package org.xmh.demo;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Hashtable;

public class FileUploadBean {
private String savePath;
private String filepath;
private String filename;
private String contentType;
private Hashtable<String, String> fields;
// 返回filename私有域的值
public String getFilename() {
return filename;
}
// 返回filepath私有域的值
public String getFilepath() {
return filepath;
}
// 返回savePath私有域的值
public void setSavePath(String savePath) {
this.savePath = savePath;
}
// 返回contentType私有域的值
public String getContentType() {
return contentType;
}
// 返回HTML表单中指定输入元素的值,元素的名字通过fieldName参数指定
public String getFieldValue(String fieldName) {
if (fields == null || fieldName == null)
return null;
return (String) fields.get(fieldName);
}
private void setFilename(String s) {
if (s == null)
return;
int pos = s.indexOf("filename=\"");
if (pos != -1) {
filepath = s.substring(pos + 10, s.length() - 1);
// Windows浏览器发送完整的文件路径和名字
// 但Linux/Unix和Mad浏览器只发送文件名字
pos = filepath.lastIndexOf("\\");
if (pos != -1)
filename = filepath.substring(pos + 1);
else
filename = filepath;
}
}
private void setContentType(String s) {
if (s == null)
return;
int pos = s.indexOf(": ");
if (pos != -1)
contentType = s.substring(pos + 2, s.length());
}
//处理请求数据的方法
public void doUpload(HttpServletRequest request) throws IOException {
ServletInputStream in = request.getInputStream();
// 创建字节数组充当缓冲容器的作用
byte[] line = new byte[128];
int i = in.readLine(line, 0, 128);
if (i < 3)
return;
// -2丢弃换行字符
int boundaryLength = i - 2;
String boundary = new String(line, 0, boundaryLength);
fields = new Hashtable<String, String>();
while(i!=-1){
String newLine=new String(line,0,i);

if(newLine.startsWith("Content-Disposition: form-data; name=\"")){
//判断文件类型
if(newLine.indexOf("filename=\"") != -1){
setFilename(new String(line,0,i-2));
if(filename == null){
return;
}
i=in.readLine(line,0,128);
setContentType(new String(line,0,i-2));
i=in.readLine(line,0,128);
newLine=new String(line,0,i);
PrintWriter pw=new PrintWriter(new BufferedWriter(new FileWriter((savePath == null ? "":savePath)+filename)));
while(i!=-1 && !newLine.startsWith(boundary)){
//文件的最后一行包含换行符
//因此必须检查当前行是否是最后一行
i=in.readLine(line,0,128);
if( (i == boundaryLength+2 || i==boundaryLength+4) && (new String(line,0,i).startsWith(boundary))){
pw.print(newLine.substring(0,newLine.length()-2));
}else{
pw.print(newLine);
}
newLine=new String(line,0,i);
}
pw.close();
}else{
//普通表单输入元素
//获取输入元素名字
int pos=newLine.indexOf("name=\"");
String fieldName=newLine.substring(pos+6,newLine.length()-3);
i=in.readLine(line,0,128);
newLine=new String(line,0,i);
StringBuffer fieldValue=new StringBuffer(128);
while(i!=-1 && !newLine.startsWith(boundary)){
//最后一行包含换行符
//因此必须检查当前行是否是最后一行
i=in.readLine(line,0,128);
if( (i==boundaryLength+2 || i==boundaryLength+4) &&(new String(line,0,i).startsWith(boundary))){
fieldValue.append(newLine.substring(0,newLine.length()-2));
}else
fieldValue.append(newLine);

newLine=new String(line,0,i);
}
fields.put(fieldName,fieldValue.toString());
}

}
i=in.readLine(line,0,128);
}
}
}

1.2 JspSmartUpload上传组件

JspSmartUpload是由JspSmart公司开发的,它可以免费下载,下载地址:
https://pan.baidu.com/s/10OTcN5GOwNly-Ty9oybwQQ,提取码:4fzf
因为要反馈给用户上传成功与否,所以需要将上传功能的执行顺序优先于表单的文本数据执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!--上传界面-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传图片</title>
</head>
<body>
<form action="upload_pic.jsp" method="post" enctype="multipart/form-data" name="form1">
<table border="1" align="center" cellpadding="1" cellspacing="1">
<tr>
<td height="45" align="center" valign="middle">
请选择上传的图片
<input type="file" name="file" />
</td>
</tr>
<tr>
<td align="center">
<input type="submit" name="submit" value="上传" />
</td>
</tr>
</table>
</form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!--处理图片 , 获取上传图图片,然后生成缩略图 -->
<%@ page language="java" pageEncoding="utf-8"
import="java.util.*,java.io.*"%>
<%@ page import="com.jspsmart.upload.SmartUpload"%>
<%@ page import="javax.servlet.jsp.tagext.TryCatchFinally"%>
<%@ page import="javax.imageio.ImageIO"%>
<%@ page import="java.awt.image.BufferedImage"%>
<%@ page import="javax.servlet.*"%>
<%@ page import="javax.servlet.http.*"%>
<%@ page import="java.awt.*" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<%
SmartUpload mySmartUpload = new SmartUpload();//实例SmartUpload对象
long file_size_max = 4000000;
String fileName2;//文件名
String ext;//文件扩展名
String url = "D:/";//应保证在WebRoot目录下有此目录的存在
//初始化
mySmartUpload.initialize(pageContext);
//只允许上载此类文件
try {
//支持上载文件的后缀名
//mySmartUpload.setAllowedFilesList("jpg,gif");
//mySmartUpload.setAllowedFilesList("jpg,gif,jpeg,png");
//不支持指定的后缀
mySmartUpload.setDeniedFilesList("exe");
//上载文件
mySmartUpload.upload();//不指定编码的upload()方法
//mySmartUpload.upload("utf-8");//指定编码的upload()方法
} catch (Exception e) {
out.print("<script type=\"text/javascript\">");
out.print("window.alert(\"文件格式不符\");");
out.print("window.location=\"upload.html;\"");
out.print("</script>");
}
try {
com.jspsmart.upload.File myFile = mySmartUpload.getFiles().getFile(0);
if (myFile.isMissing()) {//如果没有拿到文件,提示
out.print("<script type=\"text/javascript\">");
out.print("window.alert(\"请先选择要上传的文件\");");
out.print("window.location=\"upload.html;\"");
out.print("</script>");
} else {
String myFileName = myFile.getFileName();//取得上载的文件的文件名
ext = myFile.getFileExt();//取得后缀名
if (!(ext.length() > 0)) {
out.println("**************myFileName的文件名是:" + myFileName);
}

int file_size = myFile.getSize();//取得文件的大小
String saveUrl = "";//文件保存路径
if (file_size < file_size_max) {
//更改文件名,取得当前上传时间的毫秒数值
Calendar calendar = Calendar.getInstance();
String fileName = String.valueOf(calendar.getTimeInMillis());//设置新的文件名
saveUrl += fileName + "." + ext;
myFile.saveAs(saveUrl, mySmartUpload.SAVE_PHYSICAL);//保存文件

//上传完成,开始生成缩略图
java.io.File file = new java.io.File(saveUrl);//读入刚才上传的文件
out.println("ext = " + ext);
String newUrl = url + fileName + "_min." + ext;//新的缩略图保存地址
System.out.println(newUrl);
BufferedImage image=ImageIO.read(file);

int imageWidth=image.getWidth(); //取出图片额宽度
int imageHeight=image.getHeight();//取出图片的高度
int n_w=0; //缩略图的宽度
int n_h=0; //缩略图的高度
System.out.println("imageWidth="+imageWidth + ";"+"imageHeight="+imageHeight);
float tempDouble;
if(imageHeight > imageWidth){
tempDouble = imageHeight /200;
}else{
tempDouble = imageWidth /200;
}
n_w = (int) (imageWidth/tempDouble);
n_h = (int) (imageHeight/tempDouble);
FileOutputStream fos=new FileOutputStream(newUrl);
BufferedImage bi=new BufferedImage(n_w,n_h,BufferedImage.TYPE_INT_RGB);
Graphics g=bi.getGraphics();
g.drawImage(image,0,0,n_w,n_h,Color.LIGHT_GRAY,null);
g.dispose();
ImageIO.write(bi,"jpg",fos);


} else {
out.print("<script type=\"text/javascript\">");
out.print("window.alert(\"上传文件大小不能超过\"+(file_size_max/1000)+\"K\");");
out.print("window.location=\"upload.html;\"");
out.print("</script>");
}
}
} catch (Exception e) {
e.printStackTrace();
}
%>
<html>
<head>
<title>处理上传的图片</title>
</head>
<body>

</body>
</html>

1.3 Cos上传组件 (Cloud Object Storage)

  • Cos组件是O'Reilly公司开发的一款免费组件。
  • Cos包下载地址:http://www.servlets.com/cos/
    2.3.1 在Cos组件中MultipartRequest类主要负责文件上传的处理
    • (1) MultipartRequest有8个构造函数,它们分别是:
      • public MulipartRequest(HttpServletRequest request,String saveDirectory) throws IOException
      • public MultipartRequest(HttpServletRequest request,String saveDirectory,int maxPostSize) throws IOException
      • public MiltipartRequest(HttpServletRequest request,String saveDirectory,int maxPostSize,FileRenamePolicy policy) throws IOException
      • public MultipartRequest(HttpServletRequest request,String saveDirectory,int maxPostSize,String encoding) throws IOException
      • public MultipartRequest(HttpServletRequest request,String saveDirectory,int maxPostSize,String encoding,FileRenamePolicy policy) throws IOException
      • public MultipartRequest(HttpServletRequest request,String saveDirectory,String encoding) throws IOException
      • public MulipartRequest(HttpServletRequest request,String saveDirectory) throws IOException
      • public MulipartRequest(HttpServletRequest request,String saveDirectory,int maxPostSize)throws IOException
    • (2) MultipartRequest类工具有8中方法:
      • public Enumeration getParameters(): 取得请求参数的名称
      • public String getParameter(String name): 此方法返回参数为name的值
      • public String[] getParameterValues(String name):当指定参数具有多个值时,此方法会返回String数组
      • public Enumeration getFileName():传回所有文件输入类型的名称
      • public String getFilesystemNames(String name): 用此方法得到上传文件的真正的文件名称,这里的name指文件输入类型的名称
      • public String getContentType(String name): 此方法得到上传文件的文件类型
      • public File getFile(String name):此方法得到一个文件对象,代表存储在服务器上的name
      • public String getOriginalFileName(String name):返回文件在修改政策有效之前的文件名称。
      • 注意:Cos组件在上传大容量文件时,效率比起前面介绍的自编写JavaBean组件和JspSmart上传组件高。
      • 案例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <!--upload.html-->
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>无标题文档</title>
    <style>

    </style>
    </head>
    <body>
    <!--enctype的值很重要,upload.jsp处理上传的JSP-->
    <form action="upload.jsp" enctype="multipart/form-data" name="form1" method="post">
    <p><input type="file" name="file1"></p>
    <p><input type="file" name="file2"></p>
    <p><input type="file" name="file3"></p>
    <p><input type="submit" name="Submit" value="上传"></p>
    </form>
    </body>
    </html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<%@ page import="java.io.File" %>
<%@ page import="com.oreilly.servlet.MultipartRequest" %>
<%@ page import="java.util.Enumeration" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
//文件上传后,保存在d:/JavaWebs
String saveDirectory="d:"+ File.separator+"JavaWebs";
//每个文化最大500M,最多三个文件,所以...
int maxPostSize=3*500*1024*1024;
//response的编码为gd2312,同时采用缺省的文件名冲突解决策略,实现上传
MultipartRequest multi=new MultipartRequest(request,saveDirectory,maxPostSize,"UTF-8");
//输出反馈信息
Enumeration files=multi.getFileNames();
while (files.hasMoreElements()){
System.err.println("ccc");
String name= (String) files.nextElement();
File f=multi.getFile(name);
if(f!=null){
String fileName=multi.getFilesystemName(name);
String lastFileName=saveDirectory+"\\"+fileName;
out.println("上传的文件:"+lastFileName);
out.println("<hr>");
}
}
%>
<html>
<head>
<title>Title</title>
</head>
<body>

</body>
</html>

以上内容大部分都是参考一本书叫做《软件开发 JSP》,感谢作者!!!!