[SPRING]ファイルのアップロード処理-(1)


スプリングガイドにファイルをアップロードするには、非常に簡単な設定だけでいいです.
スプリングブートでのファイルのアップロードに関する設定は、次のとおりです.
1)個別のファイルアップロードライブラリ(commons-fileload)を使用します.
2)サーブレット3バージョンから追加されたファイルを使用してライブラリをアップロードします.
.
プロジェクトを実行するWASバージョンが低い場合、またはWAS以外の環境でSpring Bootプロジェクトを実行する場合は、別のライブラリを使用することをお勧めしますが、サーバベースに設定してみてください.
ほとんどのWebアプリケーションでは、画像ファイルなどのアップロード時にサムネイルを作成して処理します.
->リストまたはクエリー画面で表示されるサムネイルを作成します.クエリー画面で、元のファイルを表示するサムネイルを作成します.

1.ファイルアップロード設定


内蔵Tomcatを使用してSpring Bootプロジェクトを実行する場合は、アプリケーションに追加のライブラリは必要ありません.propertiesファイルを変更すれば十分です.
  • spring.servlet.multipart.enabled:ファイルをアップロードできるかどうかを選択する
  • spring.servlet.multipart.location:アップロードファイルの一時記憶パス
  • spring.servlet.multipart.max-request-size:1回最大アップロード可能容量(30 MB)
  • spring.servlet.multipart.max-file-size:1ファイルの最大サイズ(10 MB)
  • part.upload.path=アップロードファイルを保存する
  • ファイルのアップロードに使用するコントローラと画面のテスト


  • 実際にアップロードされたファイル処理はコントローラによって処理されます.

  • したがって、スプリングはファイルタイプの一部を提供し、追加の処理を必要とせずに使用できます.

  • 例では、ファイルのアップロードに関連するすべての操作がAjaxで処理されるため、アップロード結果に個別の画面を作成する必要はありません.

  • すべてのアップロード結果はJSON形式で作成されます.

  • コントローラはコントローラパッケージを作成し、UploadControllerクラスに追加します.
  • @RestController
    @Log4j2
    public class uploadController{
    
    	@PostMapping("/uploadAjax")
        public void uploadFile(MultipartFile[] uploadFiles){	
        //MultipartFile은 단건만 배열로 설정하면 다수의 파일을 받을 수있습니다.
    	//배열을 활용하면 동시에 여러개의 파일 정보를 처리할 수 있으므로 화면에서 여러개의 파일을 동시에 업로드 할 수 있습니다.
        
        for(MultipartFile uploadFile : uploadFiles){
        	//브라우저에 따라 업로드하는 파일의 이름은 전체경로일 수도 있고(Internet Explorer),
    		//단순히 파일의 이름만을 의미할 수도 있습니다.(chrome browser)
            String originalName = uploadFile.getOriginalFilename();//파일명:모든 경로를 포함한 파일이름
            String fileName = originalName.subString(originalName.lastIndexOf("//")+1);
            //예를 들어 getOriginalFileName()을 해서 나온 값이 /Users/Document/bootEx 이라고 한다면 
            //"마지막으로온 "/"부분으로부터 +1 해준 부분부터 출력하겠습니다." 라는 뜻입니다.따라서 bootEx가 됩니다.
            log.info("fileName" + fileName);
            }//end for
            }
            }

    テスト用のコントローラと画面

  • 実際のアップロードはブラウザでJQueryとして処理されるため、アップロードテストコントローラをConrollerパッケージに追加し、Get方式で画面を表示することができる.
  • @Controller
    public class UploadTestController{
    	
        @GetMapping("/uploadEx")
        public void uploadEx(){
        }
        }
  • 以降のtemplatesフォルダにuploadExがあります.htmlファイルを追加して、画面の内容を整理します.
  • ファイルを
  • Ajaxにアップロードするには、歌詞のFormオブジェクトを作成して使用します.
  • ファイルデータを含む
  • FormDataという名前のオブジェクトに送信するコンテンツを追加できます.
  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <input name="uploadFiles" type="file" multiple>
    <button class="uploadBtn">Upload</button>
     <script src="https://code.jquery.com/jquery-3.5.1.min.js"
                integrit="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
                crossorigin="anonymous">
        </script>
        <script>
            $('.uploadBtn').click(function( ) {
    
                var formData = new FormData();	//FormData 객체 생성
    
                var inputFile = $("input[type='file']");	
                //input 태그의 type이 file인것을 찾아서 inputFile이라는 변수로 지정
    
                var files = inputFile[0].files;
                //files : 선택한 모든 파일을 나열하는 FileList 객체입니다.
                //multiple 특성을 지정하지 않닸다면 두 개 이상의 파일을 포함하지 않습니다.
    
                for (var i = 0; i < files.length; i++) {
                    console.log(files[i]);
                    formData.append("uploadFiles", files[i]);//키,값으로 append 
                }
    
               //실제 업로드 부분
               //upload ajax
               $.ajax({
                   url: '/uploadAjax',	//경로
                   processData: false,	//기본값은 true
                   //ajax 통신을 통해 데이터를 전송할 때, 기본적으로 key와 value값을 Query String으로 변환해서 보냅니다.
                   contentType: false,	// multipart/form-data타입을 사용하기위해 false 로 지정합니다.
                   data: formData,
                   type: 'POST',
                   dataType:'json',
                   success: function(result){
                       //나중에 화면 처리
                       console.log(result);
                   },
                   error: function(jqXHR, textStatus, errorThrown){	//오류 메시지 판정
                       console.log(textStatus);
                   }
    
               }); //$.ajax
           });
    
        </script>
    
    </body>
    </html>
    


    2.アップロードしたファイルを保存する

  • ファイルのアップロードが確認された場合は、実際にアップロードされたファイルを保存する必要があります.
  • スプリング自体が提供するFileCopyUtilsを使用してもよいし、TransferTo()を使用して複数のファイルを保存してもよい.
  • ファイルを保存する場合、パスは設定ファイルによって保存され、使用されます.属性に個別の設定値を追加し、Upload Controlで設定を作成します.
  • 現在のプロジェクトのグループ名+アップロード+pathを指定し、必要なファイルのパスを記録します.
  • @RestController
    @Log4j2
    public class UploadController{
    
    	<--------추가된 부분--------->
    	@Value("${part4.upload.path})//application.properties의 변수
        private String uploadPath;
        //@Value를 import할때 springframwork.beans.factory.annotation.Value;를 선택!
        <--------추가된 부분--------->
    
        
        @PostMapping("/uploadAjax)
        public void uploadFile(MultipartFile[] uploadfiels){
        //생략
        }

    ファイルを保存する際に考慮すべき事項

  • にアップロードされた拡張子は、画像(添付ファイル付きリモートユニット)に限定されるようにチェックする必要があります.
    -拡張子をチェック!
  • アップロードされたファイル名が
  • の場合、既存のファイルを上書きする問題
  • アップロードファイルを格納フォルダ容量
  • 同名ファイルの問題

  • 添付ファイル名が同じ場合、既存のファイルが消え、新しいファイルに変更されるため、問題が発生する可能性があります.
  • これを防ぐには、一意の名前を作成し、ファイル名として使用する必要があります.
  • で最も一般的な方法は、次のとおりです.
    -1)ファイル名に時間値を追加します.
    -2)UUIDを使用して一意の値を作成する方法.(java.utilパッケージのUUIDを使用)
    (ファイル名は「UUID値ファイル名」として保存されます.)
    -3)これにより、実際のフォルダがUUID値をファイル名として使用しているため、同名ファイルのみに異なる名前を付与することができるという上書き問題の発生を防止することができる.
  • 同じフォルダのファイルが多すぎます

  • でアップロードされたファイルを同じフォルダに配置すると、ファイルが過剰に蓄積され、パフォーマンスが低下します.
  • で最も重要なのは、オペレーティングシステムが1つのフォルダに格納できるファイルの数を制限していることです.
    (FAT 32メソッドには65354の制限があります.)
  • 通常最も一般的な方法は、ファイルを保存するときに、1つのフォルダにファイルが過剰に蓄積されないように、年/月/日フォルダを個別に作成することです.

  • ファイルの拡張子を確認

  • 添付ファイルを使用して「Shellスクリプト」ファイルをアップロードして攻撃するなどの技術を使用するため、ブラウザでファイルをアップロードしたり、サーバからファイルを保存したりしながら、これらのファイルを確認する必要があります.
  • この処理は、複数のファイルから提供されるgetContentType()を用いて処理することができる.
  • @RestController
    @Log4j2
    public class UploadController {
    
        @Value("${part4.upload.path}") 
        private String uploadPath;
    
        @PostMapping("/uploadAjax")
        public void uploadFile(MultipartFile[] uploadFiles) {
        
         for(MultipartFile uploadFile : uploadFiles){
         
         <---------추가----------->
         if(uploadfile.getContentType().startWith("image") == false{
         	log.warn("this file is not image type");
            return;
            }
         </---------추가-----------/>
            String originalName = uploadFile.getOriginalFilename();
            String fileName = originalName.subString(originalName.lastIndexOf("//")+1);
            
            log.info("fileName" + fileName);
         <---------추가----------->
    
            //날짜 폴더 생성
            String folderPath = makeFolder();
            //UUID
            String uuid = UUID.randomUUID().toString();
            //저장할 파일 이름 중간에 "_"를 이용하여 구분
            String saveName = uploadPath + File.separator + folderPath +File.separator + uuid + "_" + fileName;
            
            Path savePath = Paths.get(saveName);
            //Paths.get() 메서드는 특정 경로의 파일 정보를 가져옵니다.(경로 정의하기)
            
            try{
            	uploadFile.transferTo(savePath)
                //uploadFile에 파일을 업로드 하는 메서드 transferTo(file)
            } catch (IOException e) {
                 e.printStackTrace();
                 //printStackTrace()를 호출하면 로그에 Stack trace가 출력됩니다.
            }
          </---------추가-----------/>
            
            }//end for
            }
          <---------추가----------->
          private String makeFolder(){
          
          	String str = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            //LocalDate를 문자열로 포멧
            String folderPath = str.replace("/". File.separator);
            //만약 Data 밑에 exam.jpg라는 파일을 원한다고 할때,
            //윈도우는 "Data\\"eaxm.jpg", 리눅스는 "Data/exam.jpg"라고 씁니다.
            //그러나 자바에서는 "Data" +File.separator + "exam.jpg" 라고 쓰면 됩니다.
            
            //make folder ==================
            File uploadPathFoler = new File(uploadPath, folderPath);
            //File newFile= new File(dir,"파일명");
            //->부모 디렉토리를 파라미터로 인스턴스 생성
            
            if(uploadPathFolder.exists() == false){
    	        uploadPathFoler.mkdirs();
                //만약 uploadPathFolder가 존재하지않는다면 makeDirectory하라는 의미입니다.
                //mkdir(): 디렉토리에 상위 디렉토리가 존재하지 않을경우에는 생성이 불가능한 함수
    			//mkdirs(): 디렉토리의 상위 디렉토리가 존재하지 않을 경우에는 상위 디렉토리까지 모두 생성하는 함수
               }
               return folderPath;
               }
            }
        
  • Paths.get()メソッドの使用

  • プロジェクトを実行し、上記のコードを使用して、指定したフォルダに年/月/日フォルダを作成し、アップロードすることを確認します。



    getContentType()メソッドの結果が気になるのでgoogling...

  • MIMEタイプ
  • MIMEタイプは、お客様が送信したドキュメントの多様性を通知するメカニズムです.
  • Webでは、ファイルの拡張子はあまり意味がありませんが、サーバがMIMEタイプを正しく設定し、各ドキュメントとともに転送することを確保することが重要です.
  • の典型的な構造
    -type/subtype
    -MIMEタイプの構造は非常に簡単です;"/"タイプとサブタイプの2つの文字列で構成されます.スペースは許可されていません.typeはカテゴリを表し、単一(離散)または複数の部分タイプであってもよい.
    -サブタイプは各タイプに限定されます.
  • MIMEタイプは大文字と小文字を区別しませんが、伝統的に小文字です.
  • タイプ