Vue.js

[Vue.js] Laravel 을 이용한 S3 파일업로드

먹세 2021. 9. 8. 17:39

vue

<label id="btn-file-label" v-bind:for="profile.id">
  <button class="btn-file px-2 ml-2" >
    <img src='file.jpg' > 파일첨부
  </button>
</label>
<input accept="image/*" v-bind:id="profile.id" style="display: none;" type="file" 
       v-on:change="myFileUpload" multiple>
       
<!-- for문으로 첨부된 파일들을 표시 -->
<div v-for="(file, index) in myFiles" v-bind:key="file.id" class="files-name">
  <span class="btn-cancel" @click="btnDeleteClick(file.id, file.file_name, file.user_id, file.user_name)"> [파일 삭제]</span>
  <span><a :href="file.file_url" target="_blank">{{file.file_name}}</a></span>
</div>

1. 실제 파일업로드 input 은 display:none으로 숨기고,

2. 커스텀 button 에 label을 씌워서 '파일첨부' 텍스트 클릭 시 파일업로드 창이 뜨게 구현

 

 

script

<script>
export default {
  data() {
    return {
      myFiles: null
    }
  },
  
  methods: {
    myFileUpload(e) {
        e.preventDefault();

        const config = {
          headers : {'content-type': 'multipart/form-data'}
        };

        const formData = new FormData();
        e.target.files.forEach(function(item) {
          formData.append('my_files[]', item);
        });

        //param.settings
        formData.append('user_id', this.profile.user_id);
        formData.append('user_name', this.profile.user_name);

        axios.post('/profile/upload', formData, config)
          .then((response) => {
            if(response.data.code == 404) { // laravel 에서 리턴해주는 custom helper
              console.log(`${response.data.error}`); // custom error message
            } else {
              this.myFiles = response.data; // return 된 값을 받아서 for문 업데이트
            }
          });
      },
  }

}
</script>

1. myFiles 라는 변수를 생성해놓고,

2. http 요청을 할 header와 formdata 들을 세팅

3. 업로드가 끝난 후 v-for 에 사용되는 myFiles 를 업데이트

 

 

laravel

route :

Route::post('/profile/upload', 'UserController@myFileUpload');

 

controller :

실제 구현시에 로직은 service로 빼는것이 유지보수에 좋지만,

지금은 흐름만 적는 것이므로 controller에서 처리

<?php
public function myFileUpload(Request $request) 
{

    if (Auth::check() && $request->hasFile('family_files')) { // 로그인과 파일이 있는지 체크
      $user = Auth::user();
      $rootPath = 'user_files'; // S3 에서의 파일 저장 경로

      foreach ($request->file('myFiles') as $file) {
        // 파일 업로드
        $userFile = new UserFile;
        $userFile->user_id = $request->user_id;
        $userFile->user_name = $request->user_name;
        
        // 파일 클릭시 원본 이미지 표시를 위해 리사이즈 세팅
        $width=600;
        $extension = $file->getClientOriginalExtension();
        $uniqid = uniqid();
        $filename = $uniqid. '_' . time() . '.' . $extension;
        $filepath = $rootPath . '/' . $filename;
        $image = Image::make($file);
        $image->width() > $width ? $width : $width=$image->width();
        $image->resize($width, null, function($constraint){
          $constraint->aspectRatio();
        })->encode($extension);
        
        // S3에 파일 저장
        Storage::cloud()->put($filepath, (string)$image);

        // 파일 경로를 DB에 저장
        $userFile->file_name = $file->getClientOriginalName();
        $userFile->file_url = Storage::cloud()->url($filepath);
        $userFile->save();
      }
		
      // 해당 유저의 파일들을 DB에서 모두 가져옴
      $userFiles = $this->getFiles($request);
      if ($userFiles->isEmpty()) {
        return errorCode(404, '파일이 없습니다.'); // custom helper 함수
      }

      $response = $userFiles;

    } else {
      return errorCode(404, '첨부파일 업로드 실패');
    }

    return $response;
    
 }

 

1. http 요청으로 넘어온 데이터들을 S3로 저장 및 DB에 저장하고

2. 유저의 파일들을 모두 다시 가져온 뒤 리턴

 

반응형