Webアプリケーションシステムの開発では、ファイルアップロードおよびダウンロード関数は非常に一般的に使用されています。今日は、Javawebでファイルアップロードとダウンロード機能の実装について話しましょう。
ファイルアップロードの場合、ブラウザはアップロードプロセス中にストリームの形でファイルをサーバーに送信します。サーブレットを直接使用してアップロードされたファイルの入力ストリームを取得してから、リクエストパラメーターを解析する場合、より面倒です。したがって、一般に、ApacheオープンソースツールのファイルアップロードコンポーネントであるCommon-Fileuploadを使用するように選択されます。 Common-FileuploadアップロードコンポーネントのJARパッケージは、Apacheの公式Webサイトにダウンロードすることも、StrutsのLIBフォルダーの下にあります。 Strutsアップロードの機能は、この実装に基づいています。 Common-FileuploadはCommon-IOパッケージに依存するため、このパッケージもダウンロードする必要があります。
1。開発環境の構築
下の図に示すように、fileuploadanddownloadプロジェクトを作成し、Apacheのcommons-fileuploadファイルアップロード関連JARパッケージを追加します。
2。ファイルアップロードを実装します
2.1。ファイルアップロードページとメッセージプロンプトページ
upload.jspページのコードは次のとおりです。
<%@ page Language = "Java" PageEncoding = "UTF-8"%> <ユーザー:<入力タイプ= "テキスト" name = "username"> <br/> upload file 1:<input "file" name = "file1"> <br/> uploadファイル2:<入力タイプ= "file" name = "file2"> <br/> <入力タイプ= "submit" value = "submit"> </form> </body> </html> print?<%@ page言語= "java" pageencoding = "utf-8"%> <
2.2。ファイルアップロード用のサーブレットの処理
uploadhandleservletのコードは次のとおりです。
me.gacl.web.controllerをパッケージ化します。 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をインポートします。 Import org.apache.commons.fileupload.servlet.servletfileupload; public class uploadhandleservlet拡張httpservlet {public void doget(httpservletrequest request、httpservletresponse応答)スローServletexception、ioexception {//アップロードされたファイルの保存されたディレクトリを取得し、アップロードされたファイルをWeb-infディレクトリに保存します。 this.getServletContext()。getRealPath( "/web-inf/upload"); file file = new file(savepath); //アップロードされたファイルの保存されたディレクトリが存在するかどうかを判断します。 // directory file.mkdir()を作成します。 } //メッセージプロンプト文字列message = ""; {// Apacheファイルアップロードコンポーネントを使用して、ファイルのアップロード手順:// 1を処理してください。 DiskFileItemFactory Factory DiskFileItemFactory = new DiskFileItemFactory()を作成します。 // 2。ファイルの作成Parser servletfileupload upload = new servletfileupload(Factory); //中国の文字盤upload.setheaderencoding( "utf-8")を解く; // 3。送信されたデータがアップロードフォームのデータであるかどうかを判断しますif(!servletfileupload.ismultipartcontent(request)){//従来の方法でデータを返します。 } // 4。 ServletFileuploadパーサーを使用して、アップロードされたデータを解析します。解析結果は、リスト<fileitem>コレクションを返します。各fileItemは、フォームフォームリスト<fileitem> list = upload.parserequest(request)の入力項目に対応します。 for(fileItem item:list){//通常の入力項目のデータがfileitem if(item.isformfield())にカプセル化されている場合{string name = item.getFieldName(); //通常の入力項目のデータのデータの文字化された問題を解決するstring value = item.getString( "utf-8"); // value = new String(value.getBytes( "ISO8859-1")、 "utf-8"); System.out.println(name + "=" + value); } else {//ファイルアイテムがアップロードされたファイルをカプセル化した場合//アップロードされたファイル名、string filename = item.getName(); System.out.println(filename); if(filename == null || filename.trim()。equals( "")){continue; } //注:さまざまなブラウザによって送信されたファイル名は異なります。一部のブラウザは、次のパスを持つファイルを送信します。C:/a/b/1.txt、一部は次のような単純なファイル名です。 //アイテムのアップロードされたファイルの入力ストリームを取得しますinputStream in = item.getInputStream(); //ファイル出力ストリームFileOutputStream Out = new FileOutputStream(SavePath + "//" + filename); //バッファバイトバッファーを作成[] = new Byte [1024]; //入力ストリーム内のデータが読み取られているかどうかの識別はint len = 0です。 //入力ストリームはバッファーループに読み取られます(len = in.read(buffer))> 0は、(len = in.read(buffer))> 0){// fileoutputStream出力ストリームを使用していることを意味します。 } //入力ストリームを閉じますin.close(); //出力ストリームを閉じます。close(); //ファイルアップロードitem.delete()を処理するときに生成された一時ファイルを削除します。 message = "ファイルアップロードは正常にアップロードされました!"; }}}} catch(Exception e){message = "ファイルアップロードFailed!"; e.printstacktrace(); } request.setattribute( "message"、message); request.getRequestDispatcher( "/message.jsp")。 } public void dopost(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {doget(request、response); }}web.xmlファイルにuploadhandleservletを登録します
<Servlet> <Servlet-Name> uploadHandLeservlet </servlet-name> <servlet-class> me.gacl.web.controller.uploadhandleservlet </servlet-class> </servlet> <servlet> <servlet-name> uploadhandleservlet </servlet-name> </サーブレットマッピング>
操作効果は次のとおりです。
下の図に示すように、ファイルがアップロードされた後、アップロードされたファイルはWeb-INFディレクトリの下のアップロードディレクトリに保存されます。
2.3。ファイルアップロードの詳細
上記のコードは、サーバー上の指定されたディレクトリにファイルを正常にアップロードできますが、ファイルアップロード機能に注意する必要がある多くの詳細があります。次のポイントは特に注意する必要があります。
1.サーバーのセキュリティを確保するには、Web-INFディレクトリなど、外部の世界で直接アクセスできないディレクトリにアップロードされる必要があります。
2。ファイルの上書きを防ぐには、ファイルをアップロードするために一意のファイル名を生成する必要があります。
3。ディレクトリの下にあまりにも多くのファイルが表示されないようにするには、ハッシュアルゴリズムを使用してストレージを分割する必要があります。
4.アップロードされたファイルの最大値は制限する必要があります。
5.アップロードされたファイルのタイプを制限するには、アップロードされたファイル名を受信するときに、接尾辞名が合法かどうかを判断します。
上記の5つの詳細な問題に応じて、uploadhandleservletを改善しましょう。改善されたコードは次のとおりです。
me.gacl.web.controllerをパッケージ化します。 java.io.fileをインポートします。 java.io.fileoutputStreamをインポートします。 java.io.ioexceptionをインポートします。 java.io.inputStreamをインポートします。 java.util.listをインポートします。 java.util.uuidをインポートします。 javax.servlet.servletexceptionをインポートします。 javax.servlet.http.httpservletをインポートします。 javax.servlet.http.httpservletrequestをインポートします。 javax.servlet.http.httpservletResponseをインポートします。 org.apache.commons.fileupload.fileitemをインポートします。 org.apache.commons.fileupload.fileuploadbaseをインポートします。 org.apache.commons.fileupload.progresslistenerをインポートします。 org.apache.commons.fileupload.disk.diskfileitemfactoryをインポートします。 Import org.apache.commons.fileupload.servlet.servletfileupload; / ** * @classname:uploadhandleservlet * @description:todo(このクラスの機能を説明するために1つの文を使用します) servletexception、ioexception {//アップロードされたファイルの保存されたディレクトリを取得し、アップロードされたファイルをWeb-INFディレクトリに保存し、外部世界から直接アクセスしてアップロードされたファイルのセキュリティを確保することを許可しません。 //アップロード中に生成された一時ファイルは、ディレクトリ文字列Temppath = this.getServletContext()。getRealPath( "/web-inf/temp");によって保存されます。ファイルtmpfile = new file(temppath); if(!tmpfile.exists()){//一時ディレクトリtmpfile.mkdir(); } //メッセージは文字列message = ""をプロンプトします。 {// Apacheファイルアップロードコンポーネントを使用して、ファイルのアップロード手順:// 1を処理してください。 DiskFileItemFactory Factory DiskFileItemFactory = new DiskFileItemFactory()を作成します。 //工場のバッファーのサイズを設定します。アップロードされたファイルサイズがバッファーのサイズを超えると、一時ファイルが生成され、指定された一時ディレクトリに保存されます。 Factory.SetsizethReshold(1024*100); //バッファサイズを100kbに設定します。指定されていない場合、バッファサイズはデフォルトでは10kbです。 // Factory.setRepository(TMPFile)のアップロード中に生成された一時ファイルのストレージディレクトリを設定します。 // 2。ファイルの作成Parser servletfileupload upload = new servletfileupload(Factory); //ファイルのアップロードアップロードをリッスンProgress upload.setProgressListener(new ProgressListener(){public void update(long pbytesread、long pcontentlength、int arg2){system.out.println( "ファイルサイズは:" + pcontentlength + "、現在処理されています:" + pbytesRead); 14608、現在処理されています:7367ファイルサイズは14608、現在処理されています:11419ファイルサイズは14608、現在処理されています:14608 */}}); //中国の文字盤upload.setheaderencoding( "utf-8")を解く; // 3。送信されたデータがアップロードフォームのデータであるかどうかを判断しますif(!servletfileupload.ismultipartcontent(request)){//従来の方法でデータを返します。 } //アップロードされた単一ファイルのサイズの最大値を設定します。これは現在1024*1024バイトに設定されています。 //アップロードされたファイルの総数の最大値を設定します。最大値は、同時にアップロードされた複数のファイルの最大サイズの合計です。 // 4。 ServletFileuploadパーサーを使用して、アップロードされたデータを解析します。解析結果はリスト<fileitem>コレクションを返します。各fileitemは、フォームフォームリスト<fileitem> list = upload.parserequest(request)の入力項目に対応します。 for(fileItem item:list){// fileItemが通常の入力項目のデータをカプセル化する場合、item.isformfield()){string name = item.getFieldName(); //通常の入力項目のデータのデータの文字化された問題を解決するstring value = item.getString( "utf-8"); // value = new String(value.getBytes( "ISO8859-1")、 "utf-8"); System.out.println(name + "=" + value); } else {// fileItemがアップロードされたファイルをカプセル化する場合//アップロードされたファイル名、string filename = item.getName(); System.out.println(filename); if(filename == null || filename.trim()。equals( "")){continue; } //注:さまざまなブラウザによって送信されたファイル名は異なります。一部のブラウザは、次のようなパスでファイル名を送信します。C:/a/b/1.txt、一部は次のような単純なファイル名です。 //アップロードされたファイル文字列fileextname = filename.substring(filename.lastindexof( "。")+1)の拡張子を取得します。 //アップロードされたファイルタイプを制限する必要がある場合、ファイル拡張子を使用して、アップロードされたファイルタイプが法的システムであるかどうかを判断できます。 //アイテムのアップロードされたファイルの入力ストリームを取得しますinputStream in = item.getInputStream(); //ファイルの名前を取得しますstring savefilename = makefilename(filename); //ファイルを取得するディレクトリ文字列realsavepath = makepath(savefilename、savepath); //ファイル出力ストリームFileOutputStream Out = new FileOutputStream(RealSavePath + "//" + SaveFileName); //バッファバイトバッファーを作成[] = new Byte [1024]; //入力ストリーム内のデータが読み取られているかどうかを判断する識別はint len = 0です。 //入力ストリームはバッファーに読み取られます(len = in.read(buffer))> 0は、(len = in.read(buffer))> 0){// fileoutputStream出力ストリームを使用して、バッファーデータを使用して指定されたディレクトリ(SavePath + "//" + filename)out.write(filename)を書き込みます。 } //入力ストリームを閉じますin.close(); //出力ストリームを閉じます。close(); //ファイルuploadを処理するときに生成された一時ファイルを削除//item.delete(); message = "ファイルアップロードは正常にアップロードされました!"; }}} catch(fileuploadbase.filesizelimitex cehceededexception e){e.printstacktrace(); request.setattribute( "message"、 "単一のファイルの最大値が超えられます!!!"); request.getRequestDispatcher( "/message.jsp")。戻る; } catch(fileuploadbase.sizelimitex cueededexception e){e.printstacktrace(); request.setattribute( "Message"、 "アップロードされたファイルの合計サイズは、制限の最大値を超えています!!!"); request.getRequestDispatcher( "/message.jsp")。戻る; } catch(Exception E){message = "ファイルアップロードFailed!"; e.printstacktrace(); } request.setattribute( "message"、message); request.getRequestDispatcher( "/message.jsp")。 } /*** @method:makefilename* @description:アップロードされたファイルのファイル名を生成し、ファイル名はuuid+ "_"+ファイルの元の名前* @anthor:发官网* @param filenameファイルの元の名前* @return uuid+ "_" //ファイルの上書きを防ぐには、ファイルをアップロードするために一意のファイル名を生成する必要があります。 return uuid.randomuuid()。toString() + "_" + filename; } / ***ディレクトリの下に多くのファイルが表示されないようにするには、ハッシュアルゴリズムを使用してストレージを分割する必要があります* @method:makepath* @description:* @anthor:the lone and rogant wolf** @param filenameファイル名、ファイル名に基づいてストレージディレクトリを生成しますsavepath){//ファイル名のハッシュコード値を取得します。 int dir1 = hashcode&0xf; // 0-15 int dir2 =(hashcode&0xf0)>> 4; // 0-15 //新しい保存ディレクトリ文字列dir = savepath + "//" + dir1 + "//" + dir2; // upload/2/3 upload/3/5 //ファイルはファイルとディレクトリファイルの両方を表すことができます。ファイル= newファイル(dir); //ディレクトリが存在しない場合(!file.exists()){//ディレクトリfile.mkdirs(); } return dir; } public void dopost(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {doget(request、response); }}上記の5つの小さな詳細を改善した後、ファイルアップロード機能は比較的完全になりました。
3。ファイルのダウンロード
3.1。ダウンロードに提供されるファイルリソースをリストします
Webアプリケーションシステム内のファイルリソースをユーザーに提供して、ダウンロードして提供します。まず、アップロードされたファイルディレクトリにすべてのファイルをリストするページが必要です。ユーザーがファイルのダウンロードHyperLinkをクリックすると、ダウンロードされ、ListFileserVletを書き込み、Webアプリケーションシステムにダウンロードしたすべてのファイルをリストします。
ListFileservletのコードは次のとおりです。
me.gacl.web.controllerをパッケージ化します。 java.io.fileをインポートします。 java.io.ioexceptionをインポートします。 java.util.hashmapをインポートします。 java.util.mapをインポートします。 javax.servlet.servletexceptionをインポートします。 javax.servlet.http.httpservletをインポートします。 javax.servlet.http.httpservletrequestをインポートします。 javax.servlet.http.httpservletResponseをインポートします。 / ** * @classname:listfileservlet * @description:Webシステム内のすべてのダウンロードされたファイル * @author:保証 * @date:2015-1-4 9:54:40 PM * */ public class listfileservlet extends httpservlet {public void doget(httpservletRexcectのリクエスト) //ファイルをアップロードするためのディレクトリを取得するstring uploadfilepath = this.getServletContext()。getRealPath( "/web-inf/upload"); //ファイル名を保存します。 // FilePathディレクトリのすべてのファイルとディレクトリを再帰的にトラバースし、マップコレクションリストファイル(新しいファイル(uploadFilePath)、filenAmemap)にファイルのファイル名を保存します; request.getRequestDispatcher( "/listfile.jsp")。 } /*** @method:listfile* @description:指定されたディレクトリ内のすべてのファイルを再帰的にトラバースします* @anthor:光克* @paramファイルはファイルを意味し、ファイル名を表す* @paramマップコレクションを表す* /public void listfile(ファイルファイル、マップ<文字列、文字列> if(!file.isfile()){//ディレクトリファイルファイルにすべてのファイルとディレクトリをリストします[] = file.listfiles(); //ファイルを転送[] for(ファイルf:ファイル){//再帰listFile(f、map); }} else { /***ファイル名を処理します。アップロードされたファイルは、uuid_file名の形で変更されます。ファイル名file.getname()。indexof( "_")のuuid_部分を削除して、文字列内の「_」文字の場所を取得します。ファイル名が9349249849-88343-8344_a_fan_davi.avi、then file.getName()。substring(file.getName( "_")+1)がa_fan_davi.aviを取得できます。 file.getName()。substring(file.getName()。indexof( "_")+1); //file.getName()ファイルの元の名前を取得します。この名前は一意なので、キーとして使用できます。 RealNameは処理された名前です。 map.put(file.getName()、realName)を繰り返すことができます。 }} public void dopost(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {doget(request、response); }}ここでは、ListFileservletのListFileメソッドについて簡単に説明します。 ListFileメソッドは、ディレクトリ内のすべてのファイルをリストするために使用されます。 ListFileメソッドは再帰を使用します。実際の開発では、データベースにテーブルを作成します。このテーブルは、アップロードされたファイル名とファイルの特定のストレージディレクトリを保存します。テーブルを照会することでファイルの特定のストレージディレクトリを知ることができ、再帰操作を使用する必要はありません。この例は、データベースがアップロードされたファイル名とファイルの特定のストレージ場所を保存せず、アップロードされたファイルのストレージ場所を使用してストレージの分解に使用されるため、再帰が必要です。再帰中、取得したファイル名は、外部からlistFileメソッドに渡されたマップコレクションに保存されるため、すべてのファイルが同じマップコレクションに保存されるようにします。
web.xmlファイルでlistfileservletを構成します
<サーブレット> servlet-name> listfileservlet </servlet-name> <servlet-class> me.gacl.web.controller.listfileservlet </servlet-class> </servlet> <servlet-mapping> <servlet-name> listfileservlet </servlet-name> <url-perthn>
ダウンロードされたファイルを表示するListFile.jspページは次のとおりです。
<%@ページ言語= "java" import = "java.util。*" pageencoding = "utf-8"%> <%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core"%> < <! - トラバースマップコレクション - > <c:foreach var = "me" items = "$ {filenamemap}"> <c:url value = "/servlet/downloadservlet" var = "downurl"> <c:filename "filename" value = "$ {me.key}"> </c href = "$ {doundurl}">ダウンロード</a> <br/> </c:foreach> </body> </html> ListFileserVletにアクセスすることにより、下の図に示すように、ListFile.jspページにダウンロードするユーザーに提供されるファイルリソースを表示できます。
3.2。ファイルのダウンロードを実装します
ファイルのダウンロードを処理するためのサーブレットを記述します。 DownloadServletのコードは次のとおりです。
me.gacl.web.controllerをパッケージ化します。 java.io.fileをインポートします。 java.io.fileinputStreamをインポートします。 java.io.ioexceptionをインポートします。 java.io.outputStreamをインポートします。 java.net.urlencoderをインポートします。 javax.servlet.servletexceptionをインポートします。 javax.servlet.http.httpservletをインポートします。 javax.servlet.http.httpservletrequestをインポートします。 javax.servlet.http.httpservletResponseをインポートします。パブリッククラスのダウンロードLoadServlet拡張httpservlet {public void doget(httpservletrequest request、httpservletresponse Response)throws servletexception、ioexception {//ファイル名を取得しますstring filename = request.getparameter( "filename"); //23239283-92489-AVATAR.AVI FILENAME = new String(filename.getBytes( "ISO8859-1")、 "utf-8"); //アップロードされたファイルは、/web-inf/upload directory string fileverootpath = this.getServletContext()。getRealPath( "/web-inf/upload");のサブディレクトリに保存されます。 //ファイルがファイル名によって配置されているディレクトリを見つけます文字列パス= findfilesavepathbyfilename(filename、filesaverootpath); //ファイルをダウンロードするファイル= newファイル(path + "//" + filename); //ファイルが存在しない場合(!file.exists()){request.setattribute( "message"、 "ダウンロードするリソースが削除されました!!"); request.getRequestDispatcher( "/message.jsp")。戻る; } //ファイル名文字列realname = filename.substring(filename.indexof( "_")+1); //応答ヘッダーを設定してブラウザを制御してファイルResponse.setheader( "content-disposition"、 "attachment; filename =" + urlencoder.encode(realname、 "utf-8"))をダウンロードします。 //ダウンロードするファイルを読み取り、ファイルに保存し、fileinputStream in = new FileInputStream(path + "//" + filename); //出力ストリームを作成しますoutputStream out = respons.getOutputStream(); //バッファバイトバッファー[] = new Byte [1024]; int len = 0; // loop入力ストリームのコンテンツをバッファーに読み取りますwhile((len = in.read(buffer))> 0){//バッファのコンテンツをブラウザーに出力して、ファイルをlored download.write(buffer、0、len); } //ファイル入力ストリームin.close(); //出力ストリームを閉じます。close(); } /*** @method:findfilesavepathbyfilename* @description:ファイル名とストレージルートディレクトリを介してダウンロードされるファイルのパスを見つける* @anthor: @param filename file name named* @param saverootpathファイルをアップロードするためのルートディレクトリ、 findfilesavepathbyfileName(string filename、string saverootpath){int hashcode = filename.hashcode(); int dir1 = hashcode&0xf; // 0-15 int dir2 =(hashcode&0xf0)>> 4; // 0-15文字列dir = saverootpath + "//" + dir1 + "//" + dir2; //アップロード/2/3アップロード/3/5ファイル= new File(dir); if(!file.exists()){// directory file.mkdirs();を作成します。 } return dir; } public void dopost(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {doget(request、response); }}web.xmlファイルでdownloadServletの構成
<サーブレット> servlet-name> downloadservlet </servlet-name> <servlet-class> me.gacl.web.controller.downloadservlet </servlet-class> </servlet-mapping> <servlet-name> downloadservlet </servet-name> <url-pattern>
[ダウンロード] HyperLinkをクリックし、ダウンロードServletにリクエストを送信し、それを処理してファイルのダウンロードを達成します。操作効果は、次の図に示されています。
実行中の結果から、ファイルのダウンロード機能が正常にファイルをダウンロードできることがわかります。
上記は、エディターが紹介したファイルのアップロードおよびダウンロード例の最も詳細な説明です(推奨)。私はそれが誰にでも役立つことを願っています。ご質問がある場合は、メッセージを残してください。編集者は、すべての人に時間内に返信します。 wulin.comのウェブサイトへのご支援ありがとうございます!