4부: 사진 업로드

지금까지 0부와 1부에서는 애플리케이션에서 사용되는 데이터 모델과 사용자 문서를 다루었고, 2부에서는 노드메일러와 Sendgrid를 사용하여 이메일을 통해 계정을 인증하는 방법을 설명했습니다. 그리고 3부에서는 세션 기반 사용자 인증에 대해 다루었습니다. 이제 사용자를 생성하고 로그인을 허용할 수 있으므로 이 사용자에게 프로필 사진을 연결하면 이상적입니다. 이를 위해서는 이미지를 업로드하고 모두 균일한 모양이 되도록 자를 수 있어야 합니다. 이제 시작하겠습니다!

필요한 자료:

  • Node.js
  • Express
  • Node.js 'fs' 라이브러리
  • 그래픽매직 바이너리

사용된 노드 모듈:

  • 카우치베이스 Node.js SDK/N1QL
  • 본문 파서
  • uuid
  • Multer
  • 그래픽 매직

요약:

터치베이스를 구축할 때 가장 어려웠던 부분 중 하나는 이미지를 저장하는 방법을 만드는 것이었습니다. 이 과정에서 프론트 엔드와 백엔드 등 여러 부분이 함께 어우러져야 하기 때문에 어려움이 많았습니다. 사용자가 이미지를 최대한 제어할 수 있도록 자르기 기능이 필요했습니다. 이를 위해서는 Angular.js용 자르기 모듈이 필요했습니다, ng-cropper에서 제공하는 백엔드에서 새로 찾은 치수로 이미지 크기를 조정하는 방법도 있습니다. 그래픽 매직. 또한 다양한 접근 방식 중에서 이러한 이미지를 저장할 형식(base64)을 선택해야 했습니다. 이 블로그 게시물에서는 자르기 및 서식 지정 등 이미지를 프론트엔드에서 백엔드로 전달하는 과정을 다룹니다.

멀티터 및 그래픽매직 설치하기

멀티터 모듈을 설정하는 것은 이 프로세스의 중요한 부분입니다. 멀티는 프론트엔드에서 게시된 이미지를 서버의 폴더에 저장하는 데 사용하는 노드 모듈입니다. 모듈을 다운로드하려면 아래 명령을 실행하세요.

우리에게 필요한 또 다른 중요한 모듈은 GraphicsMagick입니다. GraphicsMagick을 다운로드하는 과정은 두 가지로 이루어져야 하는데, 시스템에 GraphicsMagick 바이너리를 설치하는 것과 GraphicsMagick 노드 모듈을 다운로드하는 것입니다. 이 조합을 통해 Node.js 애플리케이션 내에서 지정된 파일 경로에서 이미지를 변경할 수 있습니다. Linux, OSX 및 Windows 시스템용 GraphicsMagick 바이너리를 다운로드하는 방법은 다음 링크에서 찾을 수 있습니다. 터치베이스 깃허브 리포지토리. 이 단계를 완료한 후 아래 명령어를 사용하여 GraphicsMagick용 노드 모듈을 다운로드합니다.

다중 설정

멀티 모듈의 설정은 다음에서 수행됩니다. app.js 파일에 저장하면 이미지가 업로드 프로세스에서 얼마나 진행되었는지 알 수 있습니다. 우리가 가장 신경 쓰는 부분은 이미지 업로드가 완료된 시점으로, 이는 다음과 같은 변수로 표시됩니다. 'done'. 이렇게 되면 파일에 안전하게 액세스하여 필요한 이미지 자르기 및 크기 축소를 수행할 수 있습니다.

앱.js 멀티터 설정

이미지 자르기 및 이미지 다운사이징을 처리하는 API 엔드포인트가 있으며(앞서 수행한 설정을 사용), 대부분의 작업은 '그림.시도' 함수를 호출합니다. 이 함수는 이미지 업로드가 완료된 후에만 실행됩니다( 완료 가 참이면), Multer는 이를 업로드 폴더에 지정된 app.js 설정으로 이동합니다. 경로 자체는 이미지 업로드가 완료되기 전에 이미지의 몇 가지 속성만 검색할 수 있습니다. 멀티터가 수신하는 이 메타데이터는 자르기 과정에서 매우 중요한 역할을 합니다.

멀티터 자체는 다음과 같은 유형의 모든 양식을 업로드하기만 하면 됩니다. <enctype=’multipart/form-data’>. 이미지는 이 양식에 대한 입력의 한 종류일 뿐이므로 양식에 다른 속성도 추가할 수 있습니다. 예를 들어, ng-cropper에서 자르기 데이터를 가져오기 위해 모든 자르기 데이터를 포함하는 객체인 양식의 숨겨진 속성을 만듭니다. 이렇게 하면 양식이 제출될 때 실행되는 HTML POST에 프런트엔드의 이미지와 메타데이터가 함께 전송됩니다. 이 과정에서 경로를 인증할 수 있도록 세션ID(3부에서 설명한)가 포함된 브라우저의 localStorage에 액세스하여 ID를 전송합니다. 이 과정에서 'Session.auth' 함수는 세션ID가 들어오는 이 상황을 처리하도록 조정됩니다. 'req.body' 객체를 반환합니다(세션ID가 멀티 메타데이터로 전송될 때 발생). 이 작업이 어떻게 수행되는지 확인하기 위해 ng-cropper의 Angular.js 구현과 자르기 데이터와 함께 이미지를 업로드하는 HTML 양식은 아래와 같습니다.

public/html/picture-partial.html에서 POST를 사용하여 여러 HTML 양식 만들기

public/js/touchbase.js 내 pictureController에서 'ng-cropper' 사용

멀티터는 양식 데이터가 백엔드로 전송될 때 두 개의 다른 부분으로 분할합니다. 업로딩된 파일에 대한 모든 메타데이터는 'req.files'. 이것은 이미지의 파일 경로, 이미지 크기, 이미지 형식 등과 같은 기본적인 사항을 알려줍니다. 이것의 다양한 측면이 우리의 '그림.시도' 함수를 호출합니다. 파일을 제외한 프런트엔드의 나머지 데이터는 다음과 같이 'req.body' 속성을 추가합니다. 여기에서 HTML 양식 속성을 사용하여 업로드한 자르기 데이터에 액세스할 수 있습니다. 이러한 다양한 매개변수에 액세스하는 방법은 양식의 여러 부분의 속성을 사용하는 것입니다. 예를 들어, 사진 업로드에 액세스할 때 프런트엔드 양식에서 파일 이름이 'userPhoto'. 이를 위한 메타데이터에 액세스하려면 다음을 살펴봅니다. 'req.files.userPhoto'. 자르기 데이터를 얻으려면 그 이름을 살펴봅니다, 'cropDim'을 클릭하고 다음을 사용하여 액세스합니다. 'req.body.cropDim'. 이 데이터는 '/api/uploadAttempt' 경로로 이동합니다.

'/api/uploadAttempt' API

이제 이 모든 데이터에 액세스할 수 있게 되었으니 이를 사용해야 합니다. 이 데이터는 '그림.시도' 함수의 models/picturemodel.js 를 사용하여 이미지를 실제로 변경할 수 있습니다. 먼저 이 이미지가 제대로 저장할 수 있는 이미지인지 확인해야 합니다. 멀티터 설정에서 app.js 최대 20MB의 이미지 업로드를 허용했습니다. 이는 오류 처리 목적으로 대부분의 경우보다 훨씬 많은 용량을 허용하는 것입니다. 파일이 제한보다 큰 크기로 업로드되는 경우, Multer는 자동으로 실패하므로 임의적으로 높은 제한을 설정했습니다. In '그림.시도'를 입력하면 이미지가 7.5MB보다 큰지 확인하고, 큰 경우 이미지를 삭제합니다. 이 두 번째 수준의 유효성 검사에서는 사용자에게 최대 파일 크기가 7.5MB이며 이미지를 업로드할 수 없음을 알리고 문제를 해결할 수 있는 방법을 안내합니다. 그리고 'fs.unlink' 명령은 멀티터에서 제공한 파일 경로를 사용하여 파일을 삭제합니다. 'req.files' 속성을 추가합니다. 그런 다음 함수는 '그림.시도'를 사용하여 앞서 언급한 파일 경로로 이미지를 조작하고 'fs' 라이브러리 및 GraphicsMagick.

'Picture.attempt' 함수

이미지에 대한 최종 유효성 검사 단계는 GraphicsMagick에서 수행합니다. 파일 유형을 확인하는 데 Multer 대신 GraphicsMagick을 사용하는 이유는 Multer가 파일 확장자만 확인하므로 내용을 반드시 나타내지 않기 때문입니다. GraphicsMagick은 파일에 대한 자체 분석을 수행합니다. 파일 형식이 허용되는 형식이 아닌 경우 업로드가 실패하고 사용자에게 오류를 알립니다. 이 유효성 검사를 통과하면 자르기 및 크기 축소를 위해 파일을 변경하기만 하면 됩니다.

GraphicsMagick을 사용하여 첫 번째 단계는 다음과 같습니다. 'autoOrient()' 를 사용하면 EXIF(이미지 파일 포맷 표준) 데이터를 사용하여 이미지가 촬영된 방향에 맞게 이미지가 올바르게 정렬됩니다. 모바일 업로드의 경우 이미지가 90도 회전되어 이상한 이미지가 될 수 있으므로 이 기능은 매우 중요합니다.

그런 다음 프론트엔드에서 얻은 자르기 데이터를 사용하여 이미지를 자릅니다. 'req.body.cropDim'. 그런 다음 이미지 높이와 너비뿐만 아니라 X 및 Y 변위와 이미지 높이와 너비가 필요한 GraphicsMagick의 자르기 함수에 전달됩니다. ng-cropper는 이 자르기 방법을 예상하고 이미지가 자를 때 이러한 속성을 제공하므로 이러한 속성을 GraphicsMagick에 직접 전달하기만 하면 간단합니다.

마지막으로 파일 크기를 줄이기 위해 이미지의 기본적인 다운사이징 작업을 수행합니다. 제 생각에는 웹사이트를 사용하고 사용자 프로필을 볼 때마다 저장하고 검색하기에는 7.5MB, 심지어 2MB는 조금 큰 용량이라고 생각합니다. 이는 애플리케이션에 큰 부담이 되지는 않지만 사용자, 특히 모바일 사용자에게 좋지 않은 경험을 제공할 수 있습니다. 몇 가지 테스트 결과, 이미지 크기를 200px로 축소하고 이미지 품질을 50%로 설정하는 것이 이미지 품질과 파일 크기 측면에서 가장 큰 이점을 제공한다는 사실을 발견했습니다. 현재 구현에서는 이미지가 150px 정사각형입니다. 이미지를 더 크게 또는 더 작게 표시하도록 선택한 경우 애플리케이션에 따라 다운사이징을 다르게 수행해야 할 수 있으므로 이 점을 염두에 두세요. 이러한 모든 변경이 끝나면 변경된 이미지가 이전 위치 위에 기록됩니다.

이미지가 올바르게 변경된 후 이미지를 다시 읽어 Javascript를 사용하여 이미지 바이너리를 base64 문자열로 변환하려고 합니다. '버퍼' 함수를 사용해야 합니다. 이렇게 하는 이유는 HTML이 이미지 태그에서 base64를 읽을 수 있으므로 프론트엔드에서 이미지를 표시할 때 렌더링을 간소화할 수 있기 때문입니다.

마지막으로 키-값 삽입 작업을 사용하여 이 base64 문자열을 업로드합니다. 이 경우 'Session.auth' 함수와 멀티 양식 데이터로 전송된 세션ID를 통해 이미지를 업로드한 사용자의 사용자 ID를 알 수 있습니다. 그런 다음 'req.userID' 에서 볼 수 있듯이 '/api/uploadAttempt' API를 호출합니다. '_픽멀티노드'가 추가된 이 userID는 이미지의 문서 ID로 사용되므로 나중에 사용자의 전체 프로필을 찾아야 할 때 이 이미지에 사용자를 쉽게 연결할 수 있습니다.

Couchbase는 지능적으로 업로드된 이 base64 문자열이 JSON이 아님을 인식하고 바이너리 유형으로 저장합니다. 이 시점 이후에는 'fs.unlink' 기능을 사용하여 사진을 삭제할 수 있습니다. 업로드 폴더로 이동합니다. 이렇게 하면 기본적으로 업로드 폴더를 버퍼로 사용한 다음 이미지의 base64 내용을 데이터베이스에 삽입한 다음 삭제하기 전에 업로드 폴더로 이동합니다. 마지막으로 N1QL 쿼리가 실행되어 해당 사용자의 'login.hasPicture' 부울 속성을 기본값인 false에서 true로 변경합니다. 이렇게 하면 사용자의 프로필에 스톡 사진이 적용되지 않고 대신 사용자가 업로드한 프로필 사진에 대한 검색이 실행됩니다.

'Picture.receive' 함수

이 모든 사진 업로드가 끝나면 각 사용자의 프로필 사진을 받을 수 있는 방법도 있어야 합니다. 이를 위해 'Picture.receive' 함수를 호출합니다. 이 함수는 '/api/advancedSearch' API routes/routes.js 이 엔드포인트는 프런트엔드에 표시할 모든 사용자와 프로필 사진을 찾아야 하기 때문입니다. 따라서 'Picture.receive' 함수는 사용자의 documentID를 입력으로 받아 해당 이미지의 base64 문자열을 반환합니다. 먼저 'login.hasPicture' 부울이 참인지 확인합니다. 그렇지 않으면 사용자에게 기본 사진을 적용합니다. 속성이 참이면 사용자의 'uuid' 속성을 가져온 다음 여기에 '_picMulterNode'를 추가한 다음 표준 키/값을 가져와 베이스64 문자열로 저장한 사용자의 이미지를 검색합니다. 이 함수의 코드는 위에서 확인할 수 있습니다.

요약하자면, 우리는 Multer를 사용하여 다음에서 파일 업로드를 처리했습니다. <enctype=’multipart/form-data’> 양식에 저장하고 업로드 폴더에 저장했습니다. 또한 이 양식 내에 숨겨진 속성을 사용하여 ng-cropper의 자르기 데이터를 저장하고 이를 멀티터에서 전송된 데이터 본문에 추가했습니다. 백엔드에서는 GraphicsMagick을 사용하여 먼저 ng-cropper 자르기 데이터로 이미지를 자르고, 더 나은 UX를 위해 이미지 크기를 줄였습니다. 이미지를 base64로 변환하여 Couchbase에 저장하고 사용자의 문서ID와 연관된 문서ID로 보관했습니다. 마지막으로 개인의 base64 이미지 문자열을 검색하는 함수를 작성하여 프론트엔드의 HTML 이미지 속성 내에서 쉽게 사용할 수 있도록 했습니다.

이것으로 터치베이스 튜토리얼 시리즈의 사진 업로드 부분을 마칩니다. 아래에 댓글로 의견을 남겨 주시고 읽어 주셔서 감사합니다!

작성자

게시자 프라나브 마유람

프라나브 마유람은 N1QL 쿼리 언어 인턴, Couchbase입니다. Couchbase Server, Node.js, Express 및 Angular.js를 사용하여 소셜 네트워크 플랫폼인 Touchbase를 구축했습니다.

댓글 남기기