Javaファイルアップロードの詳細

15894 ワード

ファイルアップロードとは?
ファイルアップロードとは、ユーザーの情報を保存することです.
なぜファイルのアップロードが必要ですか?
ユーザー登録の際、ユーザーが写真を提出する必要がある場合があります.では、この写真は保存するべきです.
コンポーネントのアップロード(ツール)
なぜアップロードツールを使用するのですか?
なぜコンポーネントをアップロードする必要がありますか?クライアントのデータを取得する場合は、getParameter()メソッドで取得するのが一般的です.
アップロードファイルデータはMIMEプロトコルにより分割され,フォームはバイナリカプセル化されている.つまり、getParameter()は、アップロードされたファイルのデータを取得できません.
まず、ファイルにhttpをアップロードする方法を見てみましょう.
  • jspページ、フォームはenctype:multipart/form-data
  • を指定する必要があります.
    
        

    1:
    2:
  • httpスナップ
  • サーブレット上でgetParameter()を使用してデータを取得しようと試みる
  • .
    
    
            String ss = request.getParameter("username");
            System.out.println(ss);
  • getParameterを直接使用してもデータは取得できません.

  • では、私たちはどうすればいいのでしょうか???requestオブジェクトはサーブレットInputStreamストリームを提供し、データを読み取ります.
  • ファイル
  • を読み込んでみました
    
            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ページにinputコントロール
  • を追加
    
    
    
  • 私がアップロードしたテキストファイルの内容は111111で、読み取り効果は以下の通りです:
  • アップロードされたファイルのデータを読み取ることができますが、どうやってファイルにアップロードされたデータと普通にサーバーに転送されたデータを分割するのでしょうか??上の図では、彼らが混ざっているのを見ました.
    私たちの普段のやり方では分割しにくいので、コンポーネントをアップロードする必要があります.
    アップロードコンポーネントには2種類あります
  • FileUpload【操作が複雑】
  • SamrtUpload【操作が簡単】
  • FileUpload
    FileUploadコンポーネントを使用するには、2つのjarパッケージをインポートする必要があります.
  • commons-io
  • Commons-fileupload

  • 開発手順
  • 解析ファクトリオブジェクトの作成【DiskFileItemFactory】
  • 解析工場を通じて解析器を作成する【サーブレットFileUpload】
  • 解析器メソッドを呼び出してrequestオブジェクトを解析し、アップロードされたすべてのコンテンツ【list】
  • を得る
  • listを巡り、各オブジェクトがアップロードファイルであるか否かを判断する
  • 通常フォームフィールドの場合、フィールド名とフィールド値
  • が得られる.
  • ファイルをアップロードする場合、InputSteamメソッドを呼び出して入力ストリームを得る、アップロードされたデータ
  • を読み出す.

    クイックスタート
    
    
            try{
            
                //1.       
                DiskFileItemFactory factory = new DiskFileItemFactory();
                
                //2.     
                ServletFileUpload upload = new ServletFileUpload(factory);
                
                //3.         
                if(!upload.isMultipartContent(request)){
                    //         ,             
                    return;
                }
                
                //     ,            
                List list = upload.parseRequest(request);  //FileItem
                
                //  list,                fileItem  
                for(FileItem item : list){
                    
                    if(item.isFormField()){
                        //         
                        String name = item.getFieldName();  //        
                        String value = item.getString();
                        System.out.println(name + "=" + value);
                    }else{
                        //       
                        String filename = item.getName();  //         C:\Documents and Settings\ThinkPad\  \1.txt
                        filename = filename.substring(filename.lastIndexOf("\\")+1);
                        InputStream in = item.getInputStream();   //      
                        int len = 0;
                        byte buffer[]= new byte[1024];
                        
                        
                        String savepath = this.getServletContext().getRealPath("/upload");
                        FileOutputStream out = new FileOutputStream(savepath + "\\" + filename);  // upload       
                        while((len=in.read(buffer))>0){
                            out.write(buffer, 0, len);
                        }
                        
                        in.close();
                        out.close();
                    }
                }
            
            }catch (Exception e) {
                e.printStackTrace();
            }

    テスト
  • 普通のフィールドもアップロードしたファイルも読めるようになりました!

  • SmartUpload
    SmartUploadコンポーネントを使用するには、smartupload.jar開発パッケージをインポートする必要があります.
    クイックスタート
    
    
            //     
            SmartUpload smartUpload = new SmartUpload();
    
            //       
            smartUpload.initialize(this.getServletConfig(), request, response);
    
    
            try {
    
                //    
                smartUpload.upload();
    
                //      ,   request              。      smartUpload
                String password = smartUpload.getRequest().getParameter("password");
                System.out.println(password);
    
                //   uploadFile    
                smartUpload.save("uploadFile");
    
    
            } catch (SmartUploadException e) {
                e.printStackTrace();
            }
    

    テスト
    同様に、uploadFileフォルダにファイルをアップロードできます.コード量も确かにかなり减っています!
    通常フィールドのパラメータも取得できます
    ファイル名をアップロードする中国語の文字化けしとデータをアップロードする中国語の文字化けし
  • 私はファイル名を中国語に変えて、文字化けしました:
  • フォームから提出された中国語のデータも文字化けした.

  • 前述したように、ファイルのデータをアップロードするフォームはバイナリパッケージされているので、requestを使用してデータを符号化し、フォームから送信されたデータには効果的ではありません!
    FileUploadの文字化けし
    FileUploadを使って文字化けし問題を解決するのは簡単です
  • 中国語のファイル名の文字化けしを解決して、解析器を得た後に、直接解析器の符号化を設けてUTF-8になります!
  • 
    
            //  upload   
            fileUpload.setHeaderEncoding("UTF-8");
    
  • フォームデータの乱符号化を解決し、フォーム値を取得する際にUTF-8符号化に従って
  • を取得する.
    
       String value = fileItem.getString("UTF-8");

    効果:
    SmartUploadの文字化けし
    このコンポーネントは文字化けしの問題を解決するのが少し面倒で、ネット上でいろいろな方法を探しても簡単な方法が見つからなかった......
    だから、もしデータが中国語に及ばないならばSmartUploadコンポーネントを使って、中国語のデータに関連してFileUploadコンポーネントを使いましょう!
    複数ファイルのアップロード、アップロードコントロールの動的追加
    現在、アップロードするファイルが複数あると仮定し、アップロードするファイルの数は不確定です.では、私たちはどうすればいいのでしょうか??
    多くのアップロードファイルのコントロールをページにリストすることはできません.これは美しくありません.ユーザーがそんなに多くのコントロールを使えなければ、無駄ですね.
    だから、私たちは動的にファイルをアップロードするコントロールを追加したいと思っています.もしユーザーがファイルをアップロードしたいなら、動的にコントロールを生成するだけでいいです.
    ぶんせき
    ページ上でコントロールを動的に生成するには、JavaScriptコードを使用することにほかならない.
    では、私たちはどうすればいいのでしょうか.
    ユーザーがファイルをアップロードしたい場合は、ボタンをクリックしてイベントをバインドし、ファイルアップロードのコントロールを生成します.
    より完璧にするために、ファイルアップロードのコントロールを生成するたびに、削除ボタンを提供して、このコントロールを削除します!
    divを使用して生成するコントロールと削除ボタンをロードする必要がありますが、ユーザーが削除をクリックすると、削除ボタンとファイルアップロードコントロールを一緒に隠す必要があります.だから、ネストdivを使ったほうがいい!
    コード#コード#
  • ページコード:
  • 
    
    
  • javaScriptコード
  • 
        
    
            function addUploadFile() {
    
                //        
                var input = document.createElement("input");
                input.type = 'file';
                input.name = 'fileName';
    
    
                //      
                var del = document.createElement("input");
                del.type = 'button';
                del.value = '  ';
    
                //     div
                var innerDiv = document.createElement("div");
    
                //          div 
                innerDiv.appendChild(input);
                innerDiv.appendChild(del);
    
                //    div  ,    div     div 
                var outterDiv = document.getElementById("file");
                outterDiv.appendChild(innerDiv);
    
                //         
                del.onclick = function dele() {
    
                    //    div remove      div  
                    this.parentNode.parentNode.removeChild(this.parentNode);
                }
    
            }
    
        
    

    ファイルアップロードの詳細
  • アップロードファイルのサイズが私たちが設定したファイルのサイズより大きい場合、ファイルはアップロード時に一時ファイルを使用してアップロードデータを保存します.アップロードが完了したら、一時ファイル
  • を削除する必要があります.
  • アップロードするファイルの位置はWEBサーバーの管理下にあることができなくて、さもなくば安全な問題をもたらす可能性があります【他の人は手段を通じてアップロードするファイルを修正する可能性があります】
  • アップロードファイル名が同じであれば、元のアップロードファイルを上書きします.ユニークなファイル名を生成します.
  • ユーザー数が多い場合は、アップロードファイルが非常に多いです.では、1つのディレクトリにすべてのアップロードファイルを保存するべきではありません.これにより、ディスクがクラッシュする可能性があります.アップロードしたファイルを別のディレクトリに分散します.

  • ぶんせき
    一時ファイルの問題を削除するのは簡単です.すべての操作が完了した後、FileItemのdelete()メソッドを呼び出すだけです.
    アップロードするファイルの位置をWEBサーバーの管理下に置くことができなくて、私達はアップロードするファイルの位置をWEB-INF/ディレクトリの下に置くことができます!
    ファイル名が同じ問題は、UID+ユーザーがアップロードしたファイル名を使用して、アップロードファイル名を保存することができます.このようなファイル名はユニークです.
    アップロードしたファイルを分散するには、HashCodeアルゴリズムを使用して分散する必要があります.
  • 下位4ビット生成一級ディレクトリ
  • 5-8ビット生成2次ディレクトリ
  • コード#コード#
    次に、比較的完全なアップロードファイルコードを書きます.
  • hashCodeアルゴリズムを使用して保存ディレクトリ
  • を分散する.
    
        private String makeDirPath(String fileName, String path) {
    
            //                 
            int hashCode = fileName.hashCode();
            int dir1 = hashCode & 0xf;
            int dir2 = (hashCode & 0xf0) >> 4;
    
            String dir = path + "\\" + dir1 + "\\" + dir2;
    
            //        ,     
            File file = new File(dir);
            if (!file.exists()) {
    
                file.mkdirs();
            }
            //     
            return dir;
    
        }
    
    
  • ユニークなファイル名
  • を生成
    
    
        private String makeFileName(String fileName) {
    
            //      UUID        ,           。
            return UUID.randomUUID().toString() + "_"+ fileName;
    
        }
  • にアップロードされたコード
  • 
    
            //    
            DiskFileItemFactory factory = new DiskFileItemFactory();
    
            //         
            ServletFileUpload fileUpload = new ServletFileUpload(factory);
    
            //  upload   
            fileUpload.setHeaderEncoding("UTF-8");
    
            //         
            if(!fileUpload.isMultipartContent(request)){
                //         ,             
                return;
            }
    
            try {
    
                //  request  ,  List【          】
                List list = fileUpload.parseRequest(request);
    
                //  List,                  
                for (FileItem fileItem : list) {
    
                    //        
                    if (fileItem.isFormField()) {
    
                        //          
                        String name = fileItem.getFieldName();
                        String value = fileItem.getString("UTF-8");
    
                        System.out.println(name + " = " + value);
                    } else {
    
                        //       
    
                        //      【     】
                        String fileName = fileItem.getName();
    
                        //     
                        fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
    
                        //          
                        fileName = makeFileName(fileName);
    
                        InputStream inputStream = fileItem.getInputStream();
    
                        //       ,          
                        String path = this.getServletContext().getRealPath("/WEB-INF/uploadFile");
    
                        //          
                        String 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つの
  • があります.
    ぶんせき
    まず、ディレクトリの下のファイルをすべて列挙します.後でファイル名に従ってファイルをダウンロードするので、すべてのファイルを1つのMapセットで保存します.
    ファイルをダウンロードする部分も簡単で、ファイル名とアップロードファイルの場所に応じて対応するファイルを見つけて読み書きし、メッセージヘッダを修正してダウンロードすればいいです.
  • は、アップロードファイルをロードするパスを取得し、すべてのファイルを再帰的に検索(ファイルが再帰出口であるか否かを判断)することにより、Mapセットに
  • をロードする.
  • Mapコレクションをフロントに転送して展示
  • を行う
  • ユーザがダウンロードをクリックすると、元の名前から絶対パス
  • を取得する.
  • リソースが存在する場合、ユーザは
  • をダウンロードすることができる.
    コード#コード#
  • WEB-INF/ディレクトリに格納ファイルをすべてMapコレクションに
  • 
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
            //         
            String filePath = this.getServletContext().getRealPath("/WEB-INF/uploadFile");
    
            Map map = new HashMap();
    
            //            ,    Map   
            getAllFiles(new File(filePath), map);
    
            request.setAttribute("map", map);
            request.getRequestDispatcher("/listFile.jsp").forward(request, response);
    
    
    
        }
    
        private void getAllFiles(File filePath, Map map) {
    
            //      ,        
            if (!filePath.isFile()) {
    
                //           (     ,      )
                File[] files = filePath.listFiles();
                for (File file : files) {
    
                    //     (      )       
                    getAllFiles(file, map);
                }
            } else {
                //   else   ,      
    
                //     
                String fileName = filePath.getName().substring(filePath.getName().lastIndexOf("_") + 1);
    
                //         key,     value   map   
                map.put(filePath.getName(), fileName);
    
            }
    
        }
    
  • ダウンロード可能ファイル
  • をJSPページに表示
    
    
    
    
    
        
            
        
        ${me.value}ダウンロード!
  • ダウンロードを実現するサーブレット
  •     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            //       
            String fileName = request.getParameter("fileName");
    
            //       ,    。
            fileName = new String(fileName.getBytes("ISO8859-1"), "utf-8");
    
            //         
            String path = this.getServletContext().getRealPath("/WEB-INF/uploadFile");
    
            //          hashCode     ,             
            String fileRealPath = makeFilePath(fileName, path);
            System.out.println(fileRealPath);
    
            //        
            File file = new File(fileRealPath);
            if (!file.exists()) {
                request.setAttribute("message", "           !");
                request.getRequestDispatcher("/message.jsp").forward(request, response);
                return ;
            }
    
            //  
    
            //              
            FileInputStream inputStream = new FileInputStream(fileRealPath);
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(bytes)) > 0) {
                response.getOutputStream().write(bytes, 0, len);
            }
    
            inputStream.close();
    
    
            //     ,     ,       
            String 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;
    
            String dir = path + "\\" + dir1 + "\\" + dir2 +"\\"+ fileName;
            return dir;
        }
    

    効果
    文章に間違いがあれば指摘を歓迎し、みんなで交流します.微信で技術的な文章を読むことに慣れている学生は、微信の公衆番号:Java 3 yに注目することができます.