Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Rails 및 Shrine으로 파일 업로드

CarrierWave, Paperclip 및 Dragonfly와 같은 많은 파일 업로드 보석이 있습니다. 그것들은 모두 고유한 특징을 가지고 있으며 아마도 당신은 이미 이러한 보석 중 하나 이상을 사용했을 것입니다.

그러나 오늘은 Janko Marohnić가 만든 비교적 새롭고 매우 멋진 솔루션인 Shrine을 소개하고자 합니다. 다른 유사한 보석과 달리 모든 기능이 모듈(또는 플러그인 신사 용어로). 검증을 지원하고 싶으십니까? 플러그인을 추가합니다. 파일 처리를 원하십니까? 플러그인 추가! 어떤 모델에 어떤 기능을 사용할 수 있는지 쉽게 제어할 수 있기 때문에 이 접근 방식이 정말 마음에 듭니다.

이 기사에서는 다음을 수행하는 방법을 보여 드리겠습니다.

  • Shrine을 Rails 애플리케이션에 통합
  • 구성(전역 및 업로더별)
  • 파일 업로드 기능 추가
  • 파일 처리
  • 검증 규칙 추가
  • Amazon S3로 추가 메타데이터 저장 및 파일 클라우드 스토리지 사용

이 기사의 소스 코드는 GitHub에서 사용할 수 있습니다.

작업 데모는 여기에서 찾을 수 있습니다.

통합 신전

시작하려면 기본 테스트 모음 없이 새 Rails 애플리케이션을 만드세요.

새로운 FileGuru -T 레일

이 데모에서는 Rails 5를 사용할 것이지만 대부분의 개념은 버전 3과 4에도 적용됩니다.

Gemfile에 Shrine gem을 드롭하세요.

보석 "신사"

그런 다음 실행:

번들 설치

이제 Photo라고 하는 모델이 필요합니다. . Shrine은 모든 파일 관련 정보를 _data로 끝나는 특수 텍스트 열에 저장합니다. 접미사. 해당 마이그레이션 생성 및 적용:

rails g 모델 사진 제목:string image_data:textrails db:migrate

이전 버전의 Rails의 경우 후자의 명령은 다음과 같아야 합니다.

rake db:이전

Shrine의 구성 옵션은 전역 및 모델별로 설정할 수 있습니다. 전역 설정은 물론 초기화 파일 내에서 수행됩니다. 필요한 파일과 플러그인을 연결하겠습니다. . 플러그인은 사용자가 사용 가능한 모든 기능을 완전히 제어할 수 있도록 하는 개별 모듈로 기능 조각을 추출하는 데 사용됩니다. 예를 들어 유효성 검사, 이미지 처리, 첨부 파일 캐싱 등을 위한 플러그인이 있습니다.

지금은 두 개의 플러그인을 추가해 보겠습니다. 하나는 ActiveRecord를 지원하고 다른 하나는 로깅을 설정합니다. 그들은 전 세계적으로 포함될 것입니다. 또한 파일 시스템 스토리지를 설정하십시오.

config/initializers/shrine.rb

"신사"가 필요합니다. "신사/저장소/파일 시스템"이 필요합니다.Shrine.plugin:activerecordShrine.plugin:logging, 로거:Rails.loggerShrine.storages ={ 캐시:Shrine::Storage::FileSystem.new("public", 접두사:"업로드/캐시"), 저장:Shrine::Storage::FileSystem.new("공개", 접두사:"업로드/저장"),}

Logger는 파일 처리에 소요된 시간을 알려주기 위해 콘솔 내부에 일부 디버깅 정보를 출력합니다. 이것은 유용할 수 있습니다.

2015-10-09T20:06:06.676Z #25602:STORE[cache] ImageUploader[:avatar] 사용자[29543] 1 파일(0.1s)2015-10-09T20:06:06.854Z #25602:PROCESS[25602] store]:ImageUploader[:avatar] 사용자[29543] 1~3개 파일(0.22s)2015-10-09T20:06:07.133Z #25602:DELETE[destroyed]:ImageUploader[:avatar] 사용자[29543] 3개 파일( 0.07초)

업로드된 모든 파일은 public/uploads에 저장됩니다. 예배 규칙서. Git에서 이러한 파일을 추적하고 싶지 않으므로 이 폴더를 제외합니다.

.gitignore

공개/업로드

이제 모델별 설정을 호스팅할 특별한 "업로더" 클래스를 만듭니다. 현재 이 클래스는 비어 있습니다.

models/image_uploader.rb

클래스 ImageUploader  

마지막으로 Photo 안에 이 클래스를 포함합니다. 모델:

모델/photo.rb

ImageUploader[:image] 포함

[:image] 양식을 구성할 때 사용할 가상 속성을 추가합니다. 위의 줄은 다음과 같이 다시 작성할 수 있습니다.

 Include ImageUploader.attachment(:image) # 또는 ImageUploader::Attachment.new(:image) 포함 

멋진! 이제 모델에 Shrine의 기능이 장착되었으며 다음 단계로 진행할 수 있습니다.

컨트롤러, 보기 및 경로

이 데모에서는 사진을 관리하는 데 컨트롤러가 하나만 필요합니다. index 페이지가 루트 역할을 합니다.

pages_controller.rb

클래스 PhotosController  

보기:

보기/사진/index.html.erb

사진

<%=link_to '사진 추가', new_photo_path %><%=@photos %> 렌더링

@photos를 렌더링하려면 배열, 부분이 필요합니다:

보기/사진/_photo.html.erb

<% if photo.image_data? %> <%=이미지 태그 photo.image_url %> <% 끝 %>

<%=사진 제목 %> | <%=link_to '편집', edit_photo_path(사진) %>

image_data? 레코드에 이미지가 있는지 여부를 확인하는 ActiveRecord에서 제공하는 방법입니다.

image_url 단순히 원본 이미지의 경로를 반환하는 Shrine 메서드입니다. 물론 작은 썸네일을 표시하는 것이 훨씬 낫지만 나중에 처리하겠습니다.

필요한 모든 경로 추가:

config/routes.rb

 리소스 :photos, only:[:new, :create, :index, :edit, :update] 루트 'photos#index'

이것입니다. 기초 작업이 완료되었으며 흥미로운 부분으로 진행할 수 있습니다!

파일 업로드

이 섹션에서는 실제로 파일을 업로드하는 기능을 추가하는 방법을 보여줍니다. 컨트롤러 작업은 매우 간단합니다.

photos_controller.rb

def new @photo =Photo.newenddef create @photo =Photo.new(photo_params) if @photo.save flash[:success] ='사진 추가!' redirect_to photos_path else 렌더링 '새' endend

유일한 문제는 강력한 매개변수의 경우 image image_data가 아닌 가상 속성 .

사진_컨트롤러.rb

privatedef photo_params params.require(:photo).permit(:title, :image)end

new 생성 보기:

보기/사진/new.html.erb

사진 추가

<%='양식' 렌더링 %>

양식의 부분도 간단합니다.

보기/사진/_form.html.erb

<%=form_for @photo do |f| %> <%=렌더링 "공유/오류", 개체:@photo %> <%=f.label :title %> <%=f.text_field :title %> <%=f.label :image %> <% =f.file_field :이미지 %> <%=f.submit %><% 끝 %>

다시 한 번 image image_data가 아닌 속성 .

마지막으로 오류를 표시하기 위해 다른 부분을 추가합니다.

보기/공유/_errors.html.erb

<% if object.errors.any? %> 

다음 오류가 발견되었습니다:

    <% object.errors.full_messages.each do |message| %>
  • <%=메시지 %>
  • <% 끝 %>
<% 끝 %>

이것이 거의 전부입니다. 지금 바로 이미지 업로드를 시작할 수 있습니다.

검증

물론 데모 앱을 완성하려면 훨씬 더 많은 작업을 수행해야 합니다. 가장 큰 문제는 사용자가 크기에 관계없이 모든 유형의 파일을 업로드할 수 있다는 것입니다. 이는 특별히 좋지 않습니다. 따라서 유효성 검사를 지원하는 다른 플러그인을 추가하십시오.

config/inititalizers/shrine.rb

Shrine.plugin:validation_helpers

ImageUploader에 대한 유효성 검사 논리 설정 :

models/image_uploader.rb

Attacher.validate do validate_max_size 1.megabyte, 메시지:"너무 큽니다(최대 1MB)" validate_mime_type_inclusion ['image/jpg', 'image/jpeg', 'image/png']end

1MB 미만의 JPG 및 PNG 이미지만 업로드할 수 있습니다. 이 규칙을 적절하게 조정하십시오.

MIME 유형

또 다른 중요한 사항은 기본적으로 Shrine이 Content-Type HTTP 헤더를 사용하여 파일의 MIME 유형을 결정한다는 것입니다. 이 헤더는 브라우저에 의해 전달되고 파일 확장자만을 기반으로 설정되며 항상 바람직한 것은 아닙니다.

파일 콘텐츠를 기반으로 MIME 유형을 결정하려면 determine_mime_type이라는 플러그인을 사용하세요. 다른 모델에는 이 기능이 필요하지 않을 수 있으므로 업로더 클래스에 포함하겠습니다.

models/image_uploader.rb

플러그인 :determine_mime_type

이 플러그인은 기본적으로 Linux의 파일 유틸리티를 사용합니다.

첨부된 이미지 캐싱

현재 사용자가 잘못된 데이터가 포함된 양식을 보내면 위에서 렌더링된 오류와 함께 양식이 다시 표시됩니다. 그러나 문제는 첨부된 이미지가 손실되고 사용자가 다시 한 번 선택해야 한다는 것입니다. cached_attachment_data라는 또 다른 플러그인을 사용하면 이 문제를 매우 쉽게 해결할 수 있습니다.

models/image_uploader.rb

플러그인 :cached_attachment_data

이제 양식에 숨겨진 필드를 추가하기만 하면 됩니다.

보기/사진/_form.html.erb

<%=f.hidden_field:이미지, 값:@photo.cached_image_data %><%=f.label:image %><%=f.file_field:이미지 %>

사진 편집

이제 이미지를 업로드할 수 있지만 수정할 수 있는 방법이 없으니 바로 수정하도록 하겠습니다. 해당 컨트롤러의 작업은 다소 사소합니다.

photos_controller.rb

def edit @photo =Photo.find(params[:id])enddef update @photo =Photo.find(params[:id]) if @photo.update_attributes(photo_params) flash[:success] ='사진 편집됨 !' redirect_to photos_path else 렌더링 '편집' 끝

동일한 _form 부분적으로 활용됩니다:

보기/사진/edit.html.erb

사진 편집

<%='양식' 렌더링 %>

좋지만 충분하지 않습니다. 사용자는 여전히 업로드된 이미지를 제거할 수 없습니다. 이를 허용하려면 다른 플러그인이 필요합니다. 

models/image_uploader.rb

플러그인:remove_attachment

:remove_image라는 가상 속성을 사용합니다. , 따라서 컨트롤러 내부에서 허용:

photos_controller.rb

def photo_params params.require(:photo).permit(:title, :image, :remove_image)end

이제 레코드에 첨부 파일이 있는 경우 이미지를 제거하는 확인란을 표시합니다.

보기/사진/_form.html.erb

<% if @photo.image_data? %> 첨부 파일 제거:<%=f.check_box :remove_image %><% end %>

썸네일 이미지 생성

현재 우리는 원본 이미지를 표시하는데, 이는 미리보기를 위한 최선의 접근 방식이 아닙니다. 사진이 크고 공간을 너무 많이 차지할 수 있습니다. 물론 CSS widthheight 속성이지만 그것도 나쁜 생각입니다. 스타일을 사용하여 이미지를 작게 설정하더라도 사용자는 여전히 원본 파일을 다운로드해야 하므로 꽤 클 수 있습니다.

따라서 초기 업로드 시 서버 측에서 작은 미리보기 이미지를 생성하는 것이 훨씬 좋습니다. 여기에는 두 개의 플러그인과 두 개의 추가 보석이 포함됩니다. 먼저 보석을 드롭하세요.

gem "image_processing"gem "mini_magick", ">=4.3.5"

Image_processing은 Shrine의 저자가 만든 특별한 보석입니다. 이미지를 조작하는 몇 가지 고급 도우미 메서드를 제공합니다. 이 보석은 ImageMagick용 Ruby 래퍼인 mini_magick에 의존합니다. 예상대로 이 데모를 실행하려면 시스템에 ImageMagick이 필요합니다.

다음과 같은 새로운 보석을 설치하십시오:

번들 설치

이제 종속성과 함께 플러그인을 포함합니다.

models/image_uploader.rb

"image_processing/mini_magick"class ImageUploader 필요  

처리는 이미지를 조작할 수 있는 플러그인입니다(예:축소, 회전, 다른 형식으로 변환 등). 버전을 사용하면 다양한 변형의 이미지를 가질 수 있습니다. 이 데모의 경우 "original" 및 "thumb"의 두 가지 버전이 저장됩니다(크기가 300x300). ).

다음은 이미지를 처리하고 두 가지 버전을 저장하는 코드입니다.

models/image_uploader.rb

클래스 ImageUploader  

resize_to_limit! image_processing gem에서 제공하는 메소드입니다. 이미지를 300x300으로 축소합니다. 더 크면 더 작고 더 작으면 아무 것도 하지 않습니다. 또한 원래의 종횡비를 유지합니다.

이제 이미지를 표시할 때 :original 또는 :thumb image_url에 대한 인수 방법:

보기/사진/_photo.html.erb

<% if photo.image_data? %> <%=이미지 태그 photo.image_url(:thumb) %> <% 끝 %>

<%=사진 제목 %> | <%=link_to '편집', edit_photo_path(사진) %>

양식 내에서도 동일하게 수행할 수 있습니다.

보기/사진/_form.html.erb

<% if @photo.image_data? %> <%=image_tag @photo.image_url(:thumb) %> 첨부 파일 제거:<%=f.check_box :remove_image %><% end %>

업로드가 완료된 후 처리된 파일을 자동으로 삭제하려면 delete_raw라는 플러그인을 추가할 수 있습니다.

models/image_uploader.rb

플러그인 :delete_raw

이미지의 메타데이터

실제로 이미지를 렌더링하는 것 외에도 메타데이터를 가져올 수도 있습니다. 예를 들어 원본 사진의 크기와 MIME 유형을 표시해 보겠습니다.

보기/사진/_photo.html.erb

<% if photo.image_data? %> <%=image_tag photo.image_url(:thumb) %>

크기 <%=photo.image[:original].size %> 바이트
MIME 유형 <%=photo.image[:original]. mime_type %>

<% 끝 %>

<%=사진 제목 %> | <%=link_to '편집', edit_photo_path(사진) %>

치수는 어떻습니까? 불행히도 기본적으로 저장되지 않지만 store_dimensions라는 플러그인을 사용하면 가능합니다.

이미지 크기

store_dimensions 플러그인은 fastimage gem에 의존하므로 지금 연결하세요:

보석 'fastimage'

실행하는 것을 잊지 마세요:

번들 설치

이제 플러그인을 포함하기만 하면 됩니다.

models/image_uploader.rb

플러그인:store_dimensions

그리고 width를 사용하여 치수를 표시합니다. 및 height 방법:

보기/사진/_photo.html.erb

<% if photo.image_data? %> <%=image_tag photo.image_url(:thumb) %>

크기 <%=photo.image[:original].size %> 바이트
MIME 유형 <%=photo.image[:original]. mime_type %>
치수 <%="#{photo.image[:original].width}x#{photo.image[:original].height}" %>

<% 끝 %>

<%=사진 제목 %> | <%=link_to '편집', edit_photo_path(사진) %>

또한 dimensions이 있습니다. 너비와 높이를 포함하는 배열을 반환하는 사용 가능한 메서드(예:[500, 750] ).

클라우드로의 이전

개발자는 업로드된 파일을 호스팅하기 위해 클라우드 서비스를 선택하는 경우가 많으며 Shrine은 그러한 가능성을 제시합니다. 이 섹션에서는 Amazon S3에 파일을 업로드하는 방법을 보여 드리겠습니다.

첫 번째 단계로 Gemfile에 두 개의 보석을 더 포함합니다. :

gem "aws-sdk", "~> 2.1"그룹:개발 젬 'dotenv-rails'end

aws-sdk는 S3의 SDK와 함께 작동하는 데 필요하지만 dotenv-rails는 개발 중인 환경 변수를 관리하는 데 사용됩니다.

번들 설치

계속하기 전에 API를 통해 S3에 액세스하려면 키 쌍을 얻어야 합니다. 이를 얻으려면 Amazon Web Services 콘솔에 로그인(또는 가입)하고 보안 자격 증명> 사용자로 이동합니다. . S3에서 파일을 조작할 수 있는 권한이 있는 사용자를 만듭니다. 다음은 S3에 대한 전체 액세스 권한을 제공하는 간단한 정책입니다.

{ "버전":"2016-11-14", "문":[ { "효과":"허용", "작업":"s3:*", "리소스":"*" } ]} 

생성된 사용자의 키 쌍을 다운로드합니다. 또는 루트 액세스 키를 사용할 수도 있지만 강력히 권장하지 않습니다. 매우 안전하지 않기 때문에 그렇게 하면 안 됩니다.

그런 다음 파일을 호스팅할 S3 버킷을 만들고 구성을 호스팅할 파일을 프로젝트의 루트에 추가합니다.

.env

S3_KEY=YOUR_KEYS3_SECRET=YOUR_SECRETS3_BUCKET=YOUR_BUCKETS3_REGION=YOUR_REGION

절대 노출하지 마세요 이 파일을 공개하고 Git에서 제외해야 합니다.

.gitignore

.env

이제 Shrine의 전역 구성을 수정하고 새로운 스토리지를 도입하십시오:

config/initializers/shrine.rb

"신사" 필요 "신사/저장소/s3"s3_options ={ access_key_id:ENV['S3_KEY'], secret_access_key:ENV['S3_SECRET'], 지역:ENV['S3_REGION'], 버킷:ENV[' S3_BUCKET'],}Shrine.storages ={ 캐시:Shrine::Storage::FileSystem.new("public", 접두사:"업로드/캐시"), 저장소:Shrine::Storage::S3.new(접두사:" 스토어", **s3_options),}

그게 다야! 앱의 다른 부분을 변경할 필요가 없으며 이 새 스토리지를 즉시 테스트할 수 있습니다. 잘못된 키와 관련하여 S3에서 오류를 수신하는 경우 후행 공백과 보이지 않는 특수 기호 없이 키와 비밀을 정확하게 복사했는지 확인하십시오.

결론

우리는 이 기사의 끝에 왔습니다. 바라건대, 지금쯤 당신은 Shrine 사용에 자신감을 느끼고 당신의 프로젝트 중 하나에 그것을 사용하기를 열망합니다. 우리는 이 gem의 많은 기능에 대해 논의했지만 파일과 함께 추가 컨텍스트를 저장하는 기능 및 직접 업로드 메커니즘과 같은 더 많은 기능이 있습니다.

따라서 사용 가능한 모든 플러그인을 철저하게 설명하는 Shrine의 문서와 공식 웹사이트를 찾아보세요. 이 보석에 대해 다른 질문이 있으면 주저하지 말고 게시하십시오. 함께 있어줘서 고맙고 곧 뵙겠습니다!