Elixir &Phoenix로 개념 검증 동적 이미지 생성기 구축

문제.


GIF는 좋지만 때로는 한 사이트에서 활력이 넘쳐 GIF가 순환 속에서 변화하지 않고 사용자의 주의력을 분산시키지 않거나 GIF의 파일 크기를 페이지 부하에 추가하지 않는 것이 좋을 수도 있다.

솔루션


우리가 구축하고자 하는 것은 소형 Phoenix 웹 프로그램으로, 사용자가 정의한 인용 그룹에서 무작위 인용과 속성의 이미지를 되돌려 주는 단점 /quote.png 이 있다.데모:

어떻게


첫 번째 문제는 사용자로부터 인용과 속성 목록을 어떻게 얻는가입니다.진정한 응용 프로그램에서, 이것은 데이터베이스와 견적을 추가하는 데 사용되는 아름다운 사용자 인터페이스의 지원을 받을 수 있다.이것은 단지 개념적 증명일 뿐이라는 것을 명심하십시오. 그래서 우리는 내가 생각할 수 있는 가장 간단한 방법을 사용할 것입니다. 그것을 검색 문자열에 넣을 것입니다.
검색 문자열의 배열 구문은 key[]=value&key[]=value2입니다. 따라서 인용부호 배열과 속성 배열을 만들면 긴 URL을 줄이는 데 도움을 주는 결과를 얻을 수 있습니다(q는 인용부호를 나타내고 a는 속성을 나타냅니다.
/quote.png?q[]=It%27s%20awesome&a[]=Mum&q[]=Pretty%20fun&a[]=Bob&q[]=Great%20stuff&a[]=Alice&q[]=Average%20at%20best&a[]=Theo
이제 우리는 데이터가 어떻게 우리의 단점에 전달될지 알게 되었으니, 우리 일을 시작합시다.

💡 First you'll need to install Phoenix. The project maintains a very good installation page so I won't repeat its contents. You can skip the node.js and Postgres sections if you don't already have them installed, we won't be needing them.


Phoenix를 설치한 후 새 항목을 만들고 프롬프트가 표시될 때 종속 항목을 설치합니다.우리는 데이터베이스나 웹 패키지를 필요로 하지 않는다. 그러면 우리는 로고가 있는 것을 뛰어넘을 수 있다.
mix phx.new image_gen_poc --no-ecto --no-webpack
선택한 편집기에서 항목을 열고 시작합시다.
끝점을 정의하기 시작합니다.image_gen_poc/lib/image_gen_poc_web/router.ex로 이동하여 19번째 행을 다음과 같이 업데이트합니다.
get "/quote.png", PageController, :index
우리는 위에서 새로운 /quote.png 단점은 index 중의 PageController 함수로 처리된 것을 볼 수 있다. 이것이 바로 우리가 다음에 해야 할 일이다.
먼저 URL에서 참조 및 속성을 추출해야 합니다. 이 작업은 Elixir 모드를 통해 쉽게 수행할 수 있습니다.
# image_gen_poc/lib/image_gen_poc_web/controllers/page_controller.ex

defmodule ImageGenPocWeb.PageController do
  use ImageGenPocWeb, :controller

  def index(conn, %{"q" => quotes, "a" => attributions}) do

    # ...

  end
end
따옴표 수조(q)는 quotes, 속성 수조aattributions에 분배된다.우리가 진일보한 토론을 하기 전에, 우리는 지금까지의 모든 것이 정상임을 확보할 것이다.그리고 우리는 require Logger 함수를 다음과 같이 업데이트index할 것이다.
defmodule ImageGenPocWeb.PageController do
  use ImageGenPocWeb, :controller
  require Logger

  def index(conn, %{"q" => quotes, "a" => attributions}) do
    Logger.info(quotes)
    Logger.info(attributions)

    render(conn, "index.html")
  end
end
cd 프로젝트 디렉터리를 가져오고 mix phx.server로 서버를 시작합니다.이제 브라우저로 이동하여 다음 URL을 붙여넣습니다.
http://localhost:4000/quote.png?q[]=It%27s%20awesome&a[]=Mum&q[]=Pretty%20fun&a[]=Bob&q[]=Great%20stuff&a[]=Alice&q[]=Average%20at%20best&a[]=Theo
터미널로 돌아가면 이런 화면을 볼 수 있습니다.
[info] GET /quote.png
[debug] Processing with ImageGenPocWeb.PageController.index/2
  Parameters: %{"a" => ["Mum", "Bob", "Alice", "Theo"], "q" => ["It's awesome", "Pretty fun", "Great stuff", "Average at best"]}
  Pipelines: [:browser]
[info] It's awesomePretty funGreat stuffAverage at best
[info] MumBobAliceTheo
[info] Sent 200 in 1ms
좋아, 좋아!
다음에 우리는 견적과 일치하는 속성을 얻어야 한다.
def index(conn, %{"q" => quotes, "a" => attributions}) do
  random_index = Enum.random(0..(length(quotes) - 1))
  quote = Enum.at(quotes, random_index)
  attribution = Enum.at(attributions, random_index)

  Logger.info(quote)
  Logger.info(attribution)

  render(conn, "index.html")
end
만약 우리가 하나의 목록만 처리한다면, 우리는 그 위에서 직접 사용할 수 있다. Enum.random/1. 그러나 두 개의sperate 목록의 같은 무작위 인덱스에서 값을 얻어야 하기 때문에, 우리는 그것으로만 인덱스를 만들 수 있다.그리고 우리는 Enum.at/2를 사용하여 두 개의 다른 목록의 같은 무작위 인덱스에서 값을 얻을 수 있다.
이제 브라우저로 돌아가 페이지를 새로 고치면 터미널에서 다음과 같은 내용이 출력됩니다.
[info] GET /quote.png
[debug] Processing with ImageGenPocWeb.PageController.index/2
  Parameters: %{"a" => ["Mum", "Bob", "Alice", "Theo"], "q" => ["It's awesome", "Pretty fun", "Great stuff", "Average at best"]}
  Pipelines: [:browser]
[info] Great stuff
[info] Alice
[info] Sent 200 in 3ms
쿼트와 속성이 일치하기 때문에 다음 작업은 그림을 만드는 것입니다!우리는 ImageMagick를 통해 이 일을 System.cmd/2 에 맡길 것이다.macOS에 ImageMagick을 설치한 것은 brew install imagemagick의 한 예일 뿐이고 다른 운영체제는 그들의 downloads page를 보십시오.System.cmd/2 수집된 명령 결과와 종료 상태 코드(0가 포함된 모듈을 되돌려줍니다. 모드가 일치합니다.
def index(conn, %{"q" => quotes, "a" => attributions}) do
  random_index = Enum.random(0..(length(quotes) - 1))
  quote = Enum.at(quotes, random_index)
  attribution = Enum.at(attributions, random_index)

  {output, 0} =
    System.cmd("convert", [
      "-background",
      "#333333",
      "-fill",
      "white",
      "-font",
      "Helvetica",
      "-pointsize",
      "56",
      "label:#{quote}", # [1]
      "-fill",
      "grey",
      "-font",
      "Helvetica-Oblique",
      "-pointsize",
      "32",
      "label:- #{attribution}", #[2]
      "-append",
      "-background",
      "#333333",
      "-gravity",
      "center",
      "-extent",
      "800x400",
      "png:-" # [3]
    ])

  render(conn, "index.html")
end
여기에는 많은 ImageMagick 설정이 있습니다. 그 중 대부분을 무시할 것입니다. 이것은 진정한 ImageMagick 강좌가 아니기 때문입니다.나는 이미 우리가 흥미를 느끼는 줄에 대해 번호를 매겼다.
  • 첫 번째 라벨은 quote의 값을 전달하고 오퍼는 자동으로 전달되기 때문에 공백이나 그 어떠한 내용도 포함할 염려가 없습니다.
  • 와 유사하게 attribution의 값은 두 번째 라벨에 전달된다.
  • png:- ImageMagick은 생성된 이미지 데이터를 PNG로 표준 출력에 출력한다고 알려줍니다.이것은 output에서 수집한 정보다.
  • 우리는 현재 output 의 이미지 데이터를 가지고 있으며, 남은 것은 그것을 클라이언트에게 되돌려 주는 것이다.render/2를 다음 부품으로 교체합니다.
    def index(conn, %{"q" => quotes, "a" => attributions}) do
    
      # ...
    
      conn
      |> put_resp_content_type("image/png")
      |> send_resp(200, output)
    end
    
    
    put_resp_content_type/2 우리가 되돌아갈 PNG에 적당한 Content-Type 헤더를 분배한 다음에 우리는 상태 코드 200과 이미지 데이터로 응답을 되돌려준다.
    만약 당신이 지금 브라우저로 돌아가서 그것을 새로 고친다면, 본문에서 시작한 그림처럼 인용된 그림을 볼 수 있을 것이다.신선함을 유지하려면 무작위로 바꿔야 한다!

    읽어주셔서 감사합니다!필요하면 소스 코드here를 찾을 수 있습니다. 질문이 있으면 아래에서 질문하십시오.💬

    좋은 웹페이지 즐겨찾기