Webアプリケーション開発では、ファイルのアップロードやダウンロード機能は、非常に一般的に使用される機能があります。
ファイルのアップロードのために、ブラウザは、それは一般的にApacheを使用して、より厄介選択されている直接使用するサーブレットは、入力にアップロードされたファイルのストリームを取得し、リクエストパラメータ内で解析する場合は、サーバーへのストリームに提出されたファイルをアップロードするプロセスでありますオープンソースツールの共通ファイルアップロードこのファイルアップロードコンポーネント。この共通ファイルアップロードのjarパッケージのアップロードコンポーネントのApacheは公式の顔をダウンロードするには、オンラインで行くことができます。共通ファイルアップロードは共通-IOのパッケージに依存しているので、パッケージをダウンロードする必要があります。
構築するための開発環境
図2に示すようにFileUploadAndDownloadは、プロジェクト、関連ジャーパッケージはApache Commonsの-ファイルアップロードファイルアップロードコンポーネントの追加を作成します。
図ジャーパッケージ20のインポート
ファイルのアップロード
●ライト・ファイルのアップロードページ、にUpload.jspページのコードは次のとおりです。
<%@ページ言語= "javaの" contentTypeの= "text / htmlの;のcharset = UTF-8"
pageEncodingは= "UTF-8" %>
<!DOCTYPE HTML>
<HTML>
<ヘッド>
<メタ文字セット= "UTF-8">
<タイトル>バンドブラザーズのIT教育</ TITLE>
</ head>の
<身体>
<フォームアクション= "$ {pageContext.request.contextPath} /アップロード"
enctype = "multipart / form-データ" 方法= "POST">
アップロードユーザー:の<input type = "text" NAME = "ユーザ名"> <br />
アップロードファイル1:<入力タイプ= "ファイル" 名= "FILE1"> <br />
アップロードファイル2:<入力タイプ= "ファイル" 名= "FILE2"> <br />
<input type = "提出" 値= "提交">
</フォーム>
</ BODY>
</ HTML>
●メッセージを作成する、次のようにページ、message.jspページコードは求められます。
<%@ページ言語= "javaの" contentTypeの= "text / htmlの;のcharset = UTF-8"
pageEncodingは= "UTF-8" %>
<!DOCTYPE HTML>
<HTML>
<ヘッド>
<メタ文字セット= "UTF-8">
<タイトル>バンドブラザーズのIT教育</ TITLE>
</ head>の
<身体>
$ {メッセージ}
</ BODY>
</ HTML>
●ライト処理ファイルアップロードサーブレット
パッケージcom.xdl.servlet。
インポートのjava.io.File;
輸入java.io.FileOutputStreamは、
インポートにjava.io.IOException;
輸入java.io.InputStreamを。
輸入はjava.util.List;
輸入javax.servlet.ServletException;
輸入javax.servlet.http.HttpServlet。
インポートのjavax.servlet.http.HttpServletRequest;
インポートのjavax.servlet.http.HttpServletResponse;
輸入org.apache.commons.fileupload.FileItem;
輸入org.apache.commons.fileupload.disk.DiskFileItemFactory;
輸入org.apache.commons.fileupload.servlet.ServletFileUpload。
パブリッククラスUploadServletはHttpServletを拡張{
プライベート静的最終長いserialVersionUIDの= 1L;
公共ボイドサービス(HttpServletRequestのリクエスト、
HttpServletResponseの応答)ServletExceptionが、IOExceptionが{スロー
//、ファイルのアップロードを保存したディレクトリを取得WEB-INFディレクトリに格納されたファイルをアップロードし、
//はアップロードされたファイルの安全性を確保するために、外の世界への直接アクセスを許可していません。
文字列関数savepath = this.getServletContext()。
getRealPath( "/ WEB-INF /アップロード");
ファイルファイル=新しいファイル(関数savepath)。
あなたが存在してアップロードするファイルを保存したディレクトリを決定する//
(もし!file.exists()&&!file.isDirectory()){
System.out.println(関数savepath +「ディレクトリが存在しない、あなたが作成する必要があります」);
//ディレクトリを作成します。
file.mkdir();
}
//メッセージプロンプト
文字列メッセージ=「」;
{試します
// Apacheのファイルアップロードコンポーネントファイルアップロード処理の手順を実行します。
1 //ファクトリを作成しますDiskFileItemFactory
DiskFileItemFactory工場=新しいDiskFileItemFactory();
// 2、ファイルのアップロードパーサーを作成します
ServletFileUploadアップロード=新しいServletFileUpload(工場)。
//中国の文字化けアップロードファイル名を解決します
upload.setHeaderEncoding( "UTF-8");
// 3、アップ提出されたデータは、データがアップロードフォームであるかどうかを判断します
(もし!ServletFileUpload.isMultipartContent(リクエスト)){
//伝統的な方法でデータを取得します
返します。
}
// 4、ServletFileUploadパーサーアップロードデータ、
//は、解像度の結果が一覧<FileItem>コレクションです返します
//各フォームFileItemのエントリに対応する形
一覧<FileItem>リスト= upload.parseRequest(リクエスト)。
{(リストFileItem項目)のために
// fileitemは、通常のデータ入力にカプセル化された場合
IF(item.isFormField()){
文字列名= item.getFieldName()。
//通常の中国のデータ入力ゴミ問題を解決します
文字列値= item.getString( "UTF-8");
System.out.println(名+ "=" +値)。
}エルス{//パッケージがfileitemアップロードされた場合
//アップロードするファイルの名前を取得し、
文字列filename = item.getName()。
System.out.println(ファイル名);
IF(ファイル名== NULL || filename.trim()。等号( "")){
持続する;
}
//ファイル名の一部だけを残して、ファイル名のファイルアップロード部分へのパスを取得するために扱います
ファイル名= filename.substring
(filename.lastIndexOf( "\\")+ 1)。
//ストリームに入力アップロードされたファイルのアイテムを取得
= item.getInputStreamに入力ストリーム();
//ファイル出力ストリームを作成します。
=アウトのFileOutputStream
新しいのFileOutputStream(関数savepath + "\\" +ファイル名);
//バッファを作成します
バイトバッファ[] =新しいバイト[1024];
//データ入力ストリーム識別子から読み取られたかどうかを判断
int型のlen = 0;
そのバッファへ//ループの入力ストリーム
(LEN = in.read(バッファ))> 0のデータがあることを意味
一方、((LEN = in.read(バッファ))> 0){
out.write(バッファ、0、LEN)。
}
//入力ストリームを閉じます
in.close();
//出力ストリームを閉じます
out.close();
//アップロードされたファイルを処理する際に発生した一時ファイルを削除
item.delete();
メッセージは「ファイルが正常にアップロード!」=;
}
}
}キャッチ(例外e){
メッセージ=「ファイルのアップロードに失敗しました!」;
e.printStackTrace();
}
request.setAttribute( "メッセージ"、メッセージ)。
request.getRequestDispatcher( "/ message.jsp")、前方(リクエスト、レスポンス)。
}
}
●web.xmlファイルでUploadServlet登録。
<?xml version = "1.0" エンコード= "UTF-8"?>
<web-appののxmlns:XSI = "http://www.w3.org/2001/XMLSchema-instance"
xmlns = "http://xmlns.jcp.org/xml/ns/javaee"
XSI:のschemaLocation = "http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
バージョン= "3.1">
<servlet>
<servlet-name>のUploadServlet </サーブレット名>
<servlet-class>のcom.xdl.servlet.UploadServlet </サーブレットクラス>
</サーブレット>
<のservlet-mapping>
<servlet-name>のUploadServlet </サーブレット名>
<url-pattern> /アップロード</のurl-pattern>
</のservlet-mapping>
</ web-app>の
Tomcatサーバを起動し、動作は21、22、23及び図24をもたらします。
21アップロードされたファイル
22個の成功したアップロードファイル
23コンソールには、アップロードするファイルの名前を印刷します
24サーバーは、クライアントのファイルのアップロードを受け取ります
ファイルのアップロードの詳細
上記のコードは成功し、その上の指定されたディレクトリ・サーバーにファイルをアップロードすることができますが、多くの小さな詳細はファイルアップロード機能が注意を払う必要がありますが、いくつか以下に示す特別な注意が必要です
●サーバーのセキュリティを確保するには、アップロードするファイルをWEB-INFディレクトリに置くなど、直接外の世界にアクセスすることはできませんディレクトリに配置する必要があります。
●アップロードされたファイルの一意のファイル名を生成するために、現象をカバーする文書を防ぐため。
●ディレクトリの下にあまりにも多くのファイルを防止するために、店舗を分割するハッシュアルゴリズムを使用します。
●最大アップロードファイルを制限するには。
●あなたが受信したときに、サフィックスの合法性を決定するために、ファイル名をアップロードし、アップロードファイルの種類を制限します。
● 针对上述提出的5点细节问题,我们来改进一下UploadServlet,改进后的代码如下:
package com.xdl.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
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.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,
// 不允许外界直接访问,保证上传文件的安全
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
// 上传时生成的临时文件保存目录
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tmpFile = new File(tempPath);
if (!tmpFile.exists()) {
// 创建临时目录
tmpFile.mkdir();
}
// 消息提示
String message = "";
try {
// 使用Apache文件上传组件处理文件上传步骤:
// 1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,
//就会生成一个临时文件存放到指定的临时目录当中。
factory.setSizeThreshold(1024 * 100);
// 设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
// 设置上传时生成的临时文件的保存目录
factory.setRepository(tmpFile);
// 2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
// 监听文件上传进度
upload.setProgressListener(new ProgressListener() {
public void update(long pBytesRead, long pContentLength,
int arg2) {
System.out.println("文件大小为:" + pContentLength
+ ",当前已处理:" + pBytesRead);
}
});
// 解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
// 3、判断提交上来的数据是否是上传表单的数据
if (!ServletFileUpload.isMultipartContent(request)) {
// 按照传统方式获取数据
return;
}
// 设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
upload.setFileSizeMax(1024 * 1024);
// 设置上传文件总量的最大值
upload.setSizeMax(1024 * 1024 * 10);
// 4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个
// List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = upload.parseRequest(request);
for (FileItem item : list) {
// 如果fileitem中封装的是普通输入项的数据
if (item.isFormField()) {
String name = item.getFieldName();
// 解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
System.out.println(name + "=" + value);
} else {// 如果fileitem中封装的是上传文件
// 得到上传的文件名称
String filename = item.getName();
System.out.println(filename);
if (filename == null || filename.trim().equals("")) {
continue;
}
// 处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename = filename.substring(
filename.lastIndexOf("\\") + 1);
// 得到上传文件的扩展名
String fileExtName =
filename.substring(filename.
lastIndexOf(".") + 1);
// 如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上
// 传的文件类型是否合法
System.out.println("上传的文件的扩展名是:" + fileExtName);
// 获取item中的上传文件的输入流
InputStream in = item.getInputStream();
// 得到文件保存的名称
String saveFilename = makeFileName(filename);
// 得到文件的保存目录
String realSavePath = makePath(saveFilename, savePath);
// 创建一个文件输出流
FileOutputStream out = new FileOutputStream
(realSavePath + "\\" + saveFilename);
// 创建一个缓冲区
byte buffer[] = new byte[1024];
// 判断输入流中的数据是否已经读完的标识
int len = 0;
// 循环将输入流读入到缓冲区当中
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
// 关闭输入流
in.close();
// 关闭输出流
out.close();
// 删除处理文件上传时生成的临时文件
// item.delete();
message = "文件上传成功!";
}
}
} catch (FileUploadBase.FileSizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "单个文件超出最大值!!!");
request.getRequestDispatcher("/message.jsp").
forward(request, response);
return;
} catch (FileUploadBase.SizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message",
"上传文件的总的大小超出限制的最大值!!!");
request.getRequestDispatcher("/message.jsp").
forward(request, response);
return;
} catch (Exception e) {
message = "文件上传失败!";
e.printStackTrace();
}
request.setAttribute("message", message);
request.getRequestDispatcher("/message.jsp").
forward(request, response);
}
private String makeFileName(String filename) {
// 为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
return UUID.randomUUID().toString() + "_" + filename;
}
/**
* 为防止一个目录下面出现太多文件,要使用hash算法打散存储
*/
private String makePath(String filename, String savePath) {
// 得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
int hashcode = filename.hashCode();
int dir1 = hashcode & 0xf;
int dir2 = (hashcode & 0xf0) >> 4;
// 构造新的保存目录
String dir = savePath + "\\" + dir1 + "\\" + dir2;
//ファイルも両方のファイルを表すディレクトリを表すことができます
ファイルファイル=新しいファイル(ディレクトリ)。
//ディレクトリが存在しない場合
(もし!file.exists()){
//ディレクトリを作成します。
file.mkdirs();
}
ディレクトリを返します。
}
}
5時細部の改良は、上述した後、それはより完璧に行われている場合でも、我々はアップロード機能を提出します。