ファイルアップロードとは何ですか?
ファイルアップロードは、ユーザー情報を保存するためです。
ファイルをアップロードする必要があるのはなぜですか?
ユーザーが登録すると、ユーザーは写真を送信する必要があります。その後、この写真は保存する必要があります。
アップロードコンポーネント(ツール)アップロードツールを使用する必要があるのはなぜですか?
コンポーネントをアップロードする必要があるのはなぜですか?クライアントのデータを取得したい場合は、通常、getParameter()メソッドを使用して取得します。
アップロードされたファイルデータはMIMEプロトコルによって分割され、フォームはバイナリにカプセル化されています。つまり、getParameter()はアップロードされたファイルのデータを取得できません。
まず、HTTPファイルのアップロードがどのようにデータを提供するかを見てみましょう
jspページ、フォームはenctype:multipart/form-dataを指定する必要があります
<form action = "$ {pagecontext.request.contextpath}/servlet/uploadservlet1" enctype = "multipart/form-data" method = "post"> upload "usures:<input type =" text "name =" username "> <br/> uploadファイル1:<入力ファイルname = "file2"> <br/> <入力タイプ= "submit" value = "submit"> </form>httpパッケージのグラブ
サーブレット上のgetParameter()を使用してデータを取得してみてください
string ss = request.getParameter( "username"); system.out.println(ss);
GetParameterを直接使用してデータを取得することはできません。
それで、私たちは何をすべきですか? ? ? ?リクエストオブジェクトは、servletinputStreamストリームを提供して、私たちにデータを読み取る
ファイルを読み取ろうとします
servletinputStream inputstream = request.getInputStream(); byte [] bytes = new byte [1024]; int len = 0; while((len = inputstream.read(bytes))> 0){system.out.println(new String(bytes、0、len)); }JSPページに追加の入力コントロールを追加します
<入力型= "text" name = "password">
アップロードしたテキストファイルは111111で、読み取り効果は次のとおりです。
これで、ファイルのアップロードのデータを読み取ることができますが、問題は次のとおりです。ファイルのアップロードされたデータをサーバーに送信したデータから分離する方法は? ? ?上記の写真で見てきましたが、それらは混合されています。
私たちの通常の練習に従って分離することは難しいので、コンポーネントをアップロードする必要があります
Fileuploadsアップロードコンポーネントには2つのタイプがあります[操作の詳細] samrtupload [その他操作] fileupload
Fileuploadコンポーネントを使用するには、2つのJARパッケージをインポートする必要があります
Commons-Io-Io-Fileupload Development Steps Parser Factoryオブジェクト[DiskFileItemFactory]を作成するパーサーファクトリー[ServletFileupload]を介してパーサーを作成します[ServletFileupload]リクエストオブジェクトを解析するために、すべてのアップロードされたコンテンツ[リスト]を取得し、各オブジェクトがアップロードされたファイルであるかどうかを判断します。通常のフォームフィールドの場合は、フィールド名とフィールド値を取得します。アップロードされたファイルの場合は、inputSteamメソッドを呼び出して入力ストリームを取得するには、アップロードされたデータをすばやくお読みください。
{// 1を試してください。 Parser Factory DiskFileItemFactory = new DiskFileItemFactory()を取得します。 // 2。 Parser ServletFileupload upload = new ServletFileupload(Factory)を取得します。 // 3。アップロードフォームのタイプを決定するif(!upload.ismultipartContent(request)){//フォームのアップロードは通常のフォームで、従来の方法でデータを取得します。 } //フォームをアップロードするには、パーサーを呼び出してアップロードされたデータリスト<FileItem> list = upload.Parserequest(request); // fileItem //リストを透過して、最初のアップロード入力item data fileitemオブジェクトをカプセル化するために使用されるfileitemオブジェクトを取得します(fileitem item:list){if(item.isformfield()){//取得するのは通常の入力項目文字列name = itemetfieldname(); //入力項目の名前を取得しますstring value = item.getString(); System.out.println(name + "=" + value); } else {//アップロード入力項目文字列filename = item.getName(); //アップロードfilename c:/documents and settings/thinkpad/desktop/1.txt filename.substring(filename.lastindexof( "//")+1)を取得します。 inputstream in = item.getInputStream(); // data int len = 0をアップロードします。バイトバッファー[] = new byte [1024];文字列SavePath = this.getServletContext()。getRealPath( "/upload"); fileoutputStream out = new fileoutputStream(savepath + "//" + filename); // fileをuploadディレクトリに書き込みますhired((len = in.read(buffer))> 0){out.write(buffer、0、len); } in.close(); out.close(); }}} catch(例外e){e.printstacktrace(); }通常のフィールドとアップロードされたファイルの両方を読み取り、取得できるとテストします!
Smartupload
Smartuploadコンポーネントを使用するには、smartupload.jar開発パッケージをインポートする必要があります
クイックスタート
//インスタンス化されたコンポーネントSMARTUPLOAD SMARTUPLOAD = new Smartupload(); //アップロード操作smartupload.initialize(this.getservletconfig()、request、response)を初期化します。 try {//準備Smartupload.upload()をアップロードしてください。 //通常のデータの場合、リクエストオブジェクトが送信されたパラメーターを取得できないほど簡単です。また、smartupload文字列パスワード= smartupload.getRequest()。getParameter( "password")に依存する必要があります。 System.out.println(パスワード); // upload uploadfileフォルダーSmartupload.save( "uploadFile"); } catch(smartuploadexception e){e.printstacktrace(); }テスト
同様に、ファイルをuploadFileフォルダーにアップロードできます。コードの量は確かに大幅に減少しています!
通常のフィールドのパラメーターを取得することもできます
ファイル名を中国の文字化けコードと、データをアップロードするための中国の文字化けコードに変更しました。
フォームによって提出された中国のデータも文字化けされています。
上記のように、ファイルデータのアップロードの形式はバイナリにカプセル化されているため、リクエストを使用してデータをエンコードすることで、フォームで送信されたデータに対しては機能しません。
fileuploadは、文字化けコードを解決します
fileuploadを使用して文字化けの問題を解決するのは非常に簡単です
文字化けされた中国のファイル名を解決します。パーサーを取得した後、パーサーのEncodingをUTF-8に設定するだけです!
//アップロードfileupload.setheaderencoding( "utf-8")のエンコードを設定します。
文字化けされたフォームデータを解決します。フォーム値を取得するときは、UTF-8エンコードを使用してそれらを取得します。
string value = fileItem.getString( "utf-8");
効果:
Smartuploadは、文字化けしたコードを解決します
このコンポーネントは、文字化けのコードの問題を解決するのに少し面倒です。私はさまざまなソリューションをオンラインで見つけましたが、簡単なものを見つけることができませんでした...
したがって、データに中国語が含まれていない場合は、Smartuploadコンポーネントを使用し、中国のデータが含まれている場合は、Fileuploadコンポーネントを使用してください。
複数のファイルをアップロードし、[アップロード]コントロールを動的に追加します
今すぐアップロードするファイルが複数あると仮定し、アップロードするファイルの数が不確実であるとします。それで、私たちは何をすべきですか? ? ?
ページにファイルをアップロードするための多くのコントロールをリストすることは不可能ですが、これは美しくありません。ユーザーがそれほど多くのコントロールを使用できない場合、それは無駄です。
したがって、ファイルをアップロードするためのコントロールを動的に追加する必要があります。ユーザーもファイルをアップロードしたい場合、コントロールを動的に生成するだけです!
分析します
ページで動的にコントロールを生成するには、JavaScriptコードを使用することに過ぎません。
それで、私たちは何をしますか? ?
これを行います:ユーザーがファイルをアップロードする場合、ボタンをクリックすると、ボタンがイベントにバインドしてファイルアップロードのコントロールを生成します。
より完全に行うために、ファイルのアップロード制御が生成されるたびに、コントロールを削除するために削除ボタンも提供されます!
Divを使用してコントロールをロードし、生成するボタンを削除する必要があります。ユーザーがクリックして削除すると、削除ボタンを非表示にし、コントロールを一緒にアップロードします。したがって、ネストされたdivを使用するのが最善です!
コードページコード:
<表> <tr> <td>アップロードユーザー:</td> <td> <入力タイプ= "Text" name ">" username "> </td> </tr </tr <tr> <td> add upload file </td> <td> <入力タイプ="ボタン "value =" value = "uploadファイル"> </td> </tr> </table>
JavaScriptコード
<script type = "text/javascript"> function adduploadfile(){//ファイルアップロード制御var input = document.createelement( "input"); input.type = 'file'; input.name = 'filename'; //削除ボタンvar del = document.createelement( "input"); del.type = 'button'; del.Value = 'Delete'; //内部div var innerdiv = document.createelement( "div"); // 2つのコントロールをInterndiv.AppendChild(入力)にバインドします。 innerdiv.appendChild(del); //外部divコントロールを取得し、内部divを外部div var outterdiv = document.getElementById( "file"); OutterDiv.AppendChild(InnerDiv); // bind event del.onclick = function delete(){//外部divの削除方法を呼び出して内部div this.parentnode.parentnode.removechild(this.parentnode); }} </script>ファイルアップロードの詳細アップロードされたファイルのサイズが設定されたファイルのサイズよりも大きい場合、ファイルは一時ファイルを使用してアップロード時にアップロードされたデータを保存します。アップロード後、一時ファイルを削除する必要があります。アップロードファイルをWebサーバーで管理できない場所は、セキュリティの問題を引き起こす可能性があります[他の人には手段を介してアップロードファイルを変更する場合があります]アップロードファイル名が同じ場合、元のアップロードファイルが上書きされます。一意のファイル名を生成したいと考えています。ユーザーの数が多い場合、多くのファイルがアップロードされています。次に、すべてのファイルを1つのディレクトリにアップロードすることはできません。これにより、ディスクがクラッシュする可能性があります。そのため、アップロードされたファイルを別のディレクトリに分散する必要があります。分析します
一時ファイルを削除する問題は非常に簡単です。すべての操作が完了した後、fileitemのdelete()メソッドを呼び出す必要があります。
アップロードされたファイルがWebサーバーによって管理されないようにするために、アップロードされたファイルの場所をWeb-INF/ディレクトリに配置できます。
同じファイル名の場合、UUID+ファイル名を使用して、ユーザーがアップロードしたファイル名としてアップロードします。このようなファイル名は一意です。
アップロードされたファイルを分割するには、ハッシュコードアルゴリズムを使用して分割する必要があります。
下の4ビットは、第1レベルのディレクトリ5-8ビットを生成しますセカンドレベルのディレクトリコード
比較的完全にアップロードされたファイルコードを記述しましょう
ハッシュコードアルゴリズムを使用して、保存されたディレクトリを分割します
private string makedirpath(string filename、string path){//ファイル名int hashcode = filename.hashcode()を介してプライマリディレクトリとセカンダリディレクトリを計算します。 int dir1 = hashcode&0xf; int dir2 =(hashcode&0xf0)>> 4;文字列dir = path + "//" + dir1 + "//" + dir2; //ディレクトリが存在しない場合は、ディレクトリファイル= newファイル(dir)を作成します。 if(!file.exists()){file.mkdirs(); } //フルパスリターンディレクトリを返します。 }一意のファイル名を生成します
private string makefileName(String filename){//アンダースコアを使用してUUIDとファイル名を分離すると、後でファイル名が解析される場合があります。 return uuid.randomuuid()。toString() + "_" + filename; }アップロードされたコード
// Factory DiskFileItemFactory Factory = new DiskFileItemFactory(); // Factory ServletFileupload fileupload = new ServletFileupload(Factory)を介してパーサーを作成します。 // fileupload.setheaderencoding( "utf-8")のアップロードコードを設定します。 //アップロードフォームのタイプを判断するif(!fileupload.ismultipartContent(request)){//フォームを通常のフォームとしてアップロードし、従来の方法でデータを取得します。 } try {//リクエストオブジェクトを解析してリスト[すべてのアップロードされたコンテンツをロード]リスト<fileItem> list = fileupload.parserequest(request); //リストを通過して、ロードされたコンテンツが通常のフィールドであるか、(fileItem fileitem:list)のアップロードファイルであるかを判断します。 string value = fileItem.getString( "utf-8"); System.out.println(name + "=" + value); } else {//アップロードファイルの場合//アップロード名[パス名を含む]文字列filename = fileItem.getName(); //ファイル名Filename = filename.substring(filename.lastindexof( "//") + 1); //一意のファイル名Filename = makefileName(filename); inputstream inputstream = fileItem.getInputStream(); //プロジェクトパスを取得し、アップロードされたファイルをプロジェクト文字列パスに書き込みます= this.getServletContext()。getRealPath( "/web-inf/uploadfile"); //散らばったディレクトリパス文字列realpath = makedirpath(filename、path)を取得します。 fileoutputStream outputStream = new fileoutputStream(realpath + "//" + filename); byte [] bytes = new byte [1024]; int len = 0; while((len = inputstream.read(bytes))> 0){outputstream.write(bytes、0、len); } inputstream.close(); outputStream.close(); //一時ファイルfileitem.delete()のデータを削除します。 }}} catch(fileuploadexception e){e.printstacktrace(); }効果:ディレクトリは正常に分割され、ファイル名は一意でした。
アップロードされたディレクトリにファイルをリストし、ダウンロードを提供します
Resposeオブジェクトを説明するとき、ファイルのダウンロードが説明されています。今回は、ファイルのダウンロードを統合するための小さなケースを書きます。
アップロードディレクトリには3つのファイルがあります
分析します
まず、ディレクトリ内のすべてのファイルをリストします。後でファイル名に従ってファイルをダウンロードする必要があるため、マップコレクションを使用してすべてのファイルを保存します
ダウンロード部分も非常に簡単です。ファイル名に従って対応するファイルを見つけてファイルの場所をアップロードし、それを書き込み、書き込み、メッセージヘッダーを変更してダウンロードを達成します。
ファイルをロードしてアップロードするパスを取得し、再帰的に(ファイルであるか再帰的な出口であるかを判断する)すべてのファイルを見つけ、マップコレクションにロードし、ユーザーがクリックしてダウンロードしたときに表示するためにマップコレクションをフロントデスクに渡し、元の名前に応じて絶対パスを取得します。リソースが存在する場合、ユーザーはコードをダウンロードし、マップコレクションのWeb-INF/ディレクトリに保存されているすべてのファイルを配置できます。
保護されたvoid dopost(httpservletrequest request、httpservletresponse応答)Swerletexception、ioexception {//アップロードされたファイルがstring filepath = this.getServletContext()。マップマップ= new Hashmap(); //再帰を使用してすべてのファイルを取得し、マップコレクションGetAllFiles(新しいファイル(FilePath)、Map)に追加します。 request.setattribute( "Map"、Map); request.getRequestDispatcher( "/listfile.jsp")。 } private void getallfiles(ファイルfilepath、マップマップ){//ファイルではない場合、それはフォルダーの場合(!filepath.isfile()){//フォルダー内のすべてのファイルをリスト(おそらくファイル、フォルダー)ファイル[] files = filepath.listfiles(); for(file file:files){//取得したファイル(またはフォルダー)とgetallfiles(file、map)を判断します。 }} else {// elseステートメントを入力してください、それはファイルでなければなりません//ファイル名文字列filename = filepath.getName()。substring(filepath.getName()。lastIndexof( "_") + 1); //ファイルのフルネームをキーとして保存し、ファイル名はマップコレクションMap.put(filepath.getName()、fileName)の値として保存します。 }}JSPページにダウンロード可能なファイルを表示します
<c:foreach items = "$ {map}" var = "me"> <c:url var = "url" value = "/downfileservlet"> <c:param name = "filename" value = "$ {me.key}"> </c:param> </c:url> $ {me.value} </a> <br> </c:foreach>ダウンロードされたサーブレットを実装します
保護されたvoid dopost(httpservletrequest request、httpservletresponse応答)servletexception、ioexception {//ファイル文字列filename = request.getparameter( "filename"); //中国のデータの場合、トランスコーディングが必要です。 filename = new String(filename.getBytes( "ISO8859-1")、 "UTF-8"); //ファイルが保存されている場所を取得しますstring path = this.getServletContext()。getRealPath( "/web-inf/uploadfile"); //ファイルはハッシュコードによってファイル名を介して保存され、ファイルはファイル名弦filrealApt = makefilepath(filename、path)を介して取得されます。 System.out.println(fileRealPath); //ファイルがfile file = new file(filearealPath)が存在するかどうかを判断します。 if(!file.exists()){request.setattribute( "message"、 "ダウンロードするリソースは存在しません!"); request.getRequestDispatcher( "/message.jsp")。戻る ; } //存在する//ファイルを読み取り、データをブラウザーに書き込みますfileinputStream inputstream = new fileinputStream(fileRealPath); byte [] bytes = new byte [1024]; int len = 0; while((len = inputstream.read(bytes))> 0){Response.getOutputStream()。書き込み(Bytes、0、len); } inputstream.close(); //メッセージヘッダーを設定して、これがダウンロードされたファイル文字列name = filename.substring(filename.lastindexof( "_") + 1)であることをブラウザに伝えます。 Response.setheader( "content-disposition"、 "attachment; filename =" + urlencoder.encode(name、 "utf-8")); } private string makefilepath(string filename、string path){int hashcode = filename.hashcode(); int dir1 = hashcode&0xf; int dir2 =(hashcode&0xf0)>> 4;文字列dir = path + "//" + dir1 + "//" + dir2 + "//" + filename; return dir; }効果
記事にエラーがある場合は、私を修正してください。誰もがお互いにコミュニケーションを取ります。 wulin.comへのご支援ありがとうございます。