Laravel 및 Vue를 사용하여 미리보기로 여러 이미지를 업로드하는 방법

이미지 업로드는 최신 웹에서 가장 인기 있는 기능 중 하나입니다. 그러나 양식을 구성할 수 있는 모든 구성 요소 중에서 이미지 업로드 구성 요소는 많은 노력과 스타일링이 필요하기 때문에 많은 개발자에게 가장 실망스러운 구성 요소 중 하나일 수 있습니다. 그래서 vue-media-upload 패키지를 만들었습니다.

Vue-Media-Upload은 만들기 및 업데이트 형식을 지원하는 미리 보기가 포함된 여러 이미지 업로드용 Vue 패키지를 쉽게 설정할 수 있으며 ajax 요청을 통해 업로드를 처리합니다.

이 튜토리얼에서는 Laravel 8, Vue 3 및 Bootstrap 5를 사용하여 이미지를 업로드할 수 있는 간단한 양식을 만듭니다.

보시다시피 미디어 업로드는 입력 파일 필드 대신 이미지를 미리 봅니다.

1단계: 백엔드 설정



먼저 데이터베이스를 준비하여 백엔드와 함께 stat을 해보자.
우리는 두 개의 테이블, 즉 posts 테이블이 필요합니다.

Schema::create('posts', function (Blueprint $table) {
  $table->id();
  $table->string('title');
  $table->string('description');
  $table->timestamps();
});


그리고 이미지 테이블

Schema::create('images', function (Blueprint $table) {
  $table->id();
  $table->foreignId('post_id')->constrained();
  $table->string('name');
  $table->timestamps();
});


모델 설정도 잊지 마세요.

2단계: 미디어 업로드 설치



npm을 통해 미디어 업로드를 설치할 수 있습니다.

$ npm install vue-media-upload


또는 원사를 통해

$ yarn add vue-media-upload


설치 후 app.js 파일로 가져올 수 있습니다.

require('./bootstrap');

import { createApp } from 'vue';

import { UploadMedia, UpdateMedia } from 'vue-media-upload';

let app=createApp({})

app.component('upload-media' , UploadMedia);
app.component('update-media' , UpdateMedia);

app.mount("#app")


3단계: 양식 만들기/추가


create.blade.php에서 두 개의 입력을 만들고 <upload-media/> 구성 요소를 사용합니다.

<form action="{{route('post.create')}}" method="post">
  @csrf
  <div class="form-group">
    <label for="">Title</label>
    <input type="text" name="title" class="form-control @error('title') is-invalid @enderror" value="{{old('title')}}
  </div>
  <div class="form-group mt-3">
    <label for="">Description</label>
    <textarea name="description" rows="4" class="form-control @error('title') is-invalid @enderror">{{old('description')}}</textarea>
  </div>
  <div class="mt-3">
    <label for="" class="m-0">Media</label>
      <div id="app">
        <upload-media 
          server='/api/upload'
          error="@error('media'){{$message}}@enderror">
        </upload-media>
      </div>
    </div>
    <button class="btn btn-primary text-white mt-4">Submit</button>
</form>


용법



이제 api.php에 이 줄을 추가해야 합니다.

//upload image
Route::post('/upload', [ImageController::class, 'store'])->name('upload');

ImageController에서 업로드된 이미지를 store()에 임시 저장하는 함수tmp\uploads를 만듭니다.

public function store(Request $request){
  $path = public_path('tmp/uploads');

  if (!file_exists($path)) {
    mkdir($path, 0777, true);
  }

  $file = $request->file('image');

  $name = uniqid() . '_' . trim($file->getClientOriginalName());

  $file->move($path, $name);

  return ['name'=>$name];
}

store() 함수는 업로드된 이미지에 고유한 이름을 지정하고 tmp/upload 에 저장하고 작업을 계속할 수 있도록 고유한 이름을 <upload-media /> 구성 요소에 반환합니다.

포스트 컨트롤러 만들기


web.php 설정

Route::get('/post/create', [PostController\Create::class, 'index']);
Route::post('/post/create', [PostController\Create::class, 'store'])->name('post.create');


그리고 생성 컨트롤러PostController/Create.php에서 store() 함수는 다음과 같습니다.

public function store(Request $request){

  $this->validate($request,[
    'title'=>'required',
    'description'=>'required',
    'media'=>'required',
  ]);

  $post = Post::create([
    'title'=>$request->title,
    'description'=>$request->description,
  ]);

  foreach($request->media as $image){     
    $from = public_path('tmp/uploads/'.$image);
    $to = public_path('post_images/'.$image);

    File::move($from, $to);
    $post->images()->create([
      'name' => $image,
    ]);
  }

  $posts = Post::get();
  return redirect()->route('post.dashboard', ['posts'=>$posts]);
}


이 코드는 단순히 게시물을 저장하고 고유한 이미지 이름을 사용하여 추가된 이미지를 임시 위치/tmp/uploads 파일에서 최종 위치/post_images로 이동합니다.
tmp/uploads/post_images 디렉토리를 생성해야 합니다!

4단계: 양식 업데이트/편집



업데이트 양식update.blade.php에서 두 번째 구성 요소<update-media/>를 사용해야 합니다.

<form action="{{route('post.update', $post->id)}}" method="post">
  @csrf
    <div class="form-group">
      <label for="">Title</label>
      <input type="text" name="title" class="form-control" value="{{$post->title}}" required>
    </div>
    <div class="form-group mt-3">
      <label for="">Description</label>
      <textarea name="description" rows="4" class="form-control" required>{{$post->description}}</textarea>
    </div>
    <div class="mt-3" id="app">
      <update-media 
        server='/api/upload' 
        media_file_path='/post_images'
        media_server="/api/media/{{$post->id}}" 
        error="@error('media'){{$message}}@enderror">
      </update-media>
    </div>
    <button class="btn btn-primary text-white mt-4">Save</button>
</form>


미리 보려면 저장된 이미지 이름이 필요하므로 api.php에 이 줄을 추가하는 것을 잊지 마십시오.

//return post images
Route::get('/media/{post}', [ImageController::class, 'getImages'])->name('post.images');


또한 getImagesImageController 함수를 추가해야 합니다.

public function getImages(Post $post){
  $images = $post->images;
  return ['media'=>$images];
}


게시물 컨트롤러 업데이트


web.php에 이 두 줄을 추가해야 합니다.

Route::get('/post/update/{post}',[PostController\Update::class, 'index']);
Route::post('/post/update/{post}',[PostController\Update::class, 'update'])->name('post.update');


마지막으로 update()PostController/Update.php 함수가 필요합니다.

public function update(Post $post, Request $request){
  $this->validate($request,[
    'title'=>'required',
    'description'=>'required',
    'media'=>'required',
  ]);

  $post->update($request->all());

  if(isset($request->added_media)){
    foreach($request->added_media as $image){

      $from = public_path('tmp/uploads/'.$image);
      $to = public_path('post_images/'.$image);

      File::move($from, $to);
      $post->images()->create([
        'name' => $image,
      ]);
    }
  }

  if(isset($request->deleted_media)){
    foreach($request->deleted_media as $deleted_media){
      File::delete(public_path('post_images/'.$deleted_media));
      Image::where('name', $deleted_media)->delete();
    }
  }

  $posts = Post::get();
  return redirect()->route('post.dashboard', ['posts'=>$posts]);
}


이 기능은 기본적으로 추가된 이미지를 추가하고 삭제된 이미지를 삭제합니다.

this repository에서 이 프로젝트를 찾을 수 있습니다.

숙제



사용자가 양식에 이미지를 업로드하고 최종 제출 전에 양식을 떠나는 상황에서 임시 이미지는 여전히 서버에 저장되며 이동하거나 삭제되지 않습니다.

이 상황을 처리하는 방법은 귀하에게 달려 있지만 Laravel scheduling을 사용하여 장인 명령을 예약하여 사용되지 않은 모든 이미지를 정리하는 것이 좋습니다.

좋은 웹페이지 즐겨찾기