Rhapsodist

ruby

Line api를 이용해서 사진 받아오기

2020.04.24

Created By Rhapsodist

Rhapsodist

Line api를 이용해서 사진 받아오기

1. 개요

Rails에서 Line Message api를 이용해 대화리스트에서 올라온 이미지를 다운 받아보자.

2. code

uri= URI.parse("https://api-data.line.me/v2/bot/message/#{content_id}/content")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
head = {
  'Content-type' => 'application/json; charset=UTF-8',
  'Authorization' => "Bearer #{ENV['LINE_CHANNEL_TOKEN']}"
}
request = Net::HTTP::Get.new(uri.path, head)
response = http.request(request)

File.open(Rails.root.join('public', 'upload', "#{content_id}.jpg"), 'wb') do |file|
  file.write(response.body)
end

라인에서 메세지에는 각각 고유의 아이디가 존재하는데, 이 메세지를 content라고 정의한다.

사진을 받기 위해서는 사진의 content 아이디를 알고 있어야 한다.

또 필요한 것은 line의 channel token이다.

2.1. Set uri

uri= URI.parse("https://api-data.line.me/v2/bot/message/#{content_id}/content")

우선 라인에서 context의 정보를 받기위한 uri를 입력한다. #{}안에는 이미지의 content id를 넣는다.

2.2. Set Header

head = {
  'Content-type' => 'application/json; charset=UTF-8',
  'Authorization' => "Bearer #{ENV['LINE_CHANNEL_TOKEN']}"
}

그 다음으로는 request의 header을 설정해 준다. Content-type은 딱히 설정을 안해줘도 괜찮은나, Authorization은 반드시 설정해야한다. #{}안에 line channel token을 입력해주면 된다. Bearer은 잊지말고 넣어주자!

2.3. Save image

File.open(Rails.root.join('public', 'upload', "#{content_id}.jpg"), 'wb') do |file|
  file.write(response.body)
end

response를 받고 body부분을 확인해 보면 binary code의 형태로 돌아온다. 원래는 send_file로 바로 front 쪽으로 보내는 방법을 생각했었지만, line에서 돌아온 binary 코드를 직접 저장하거나, send_file처럼 바로 file로 사용하려고 하면 다음과 같은 에러가 발생한다.

Encoding::UndefinedConversionError ("\xFF" from ASCII-8BIT to UTF-8):

binary code가 깨져있다는 것인데, 인코딩 과정에서 뭔가 문제가 있는듯 하다.

nodejs에서는

const options = {
  url: `https://api.line.me/v2/bot/message/${content_id}/content`,
  method: 'get',
  headers: {
      'Authorization': 'Bearer ' + accessToken,
  },
  encoding: null
}

처럼 간단히 request options에 encoding: null만 해주면 encode 에러 없이 사용할 수 있지만,

루비에서 저 방식을 어떻게 해야하는지 나는 모르겠다. 한참을 조사해봤지만 방법을 알아낼 수 없었다.

현재 진행중인 프로젝트에서 bot server에 직접 image를 저장하지 않고 line의 server에 저장되어있는 image를 불러와서 쓰고, 그 이미지 파일은 보관하지 않는 계획이었기 때문에, 방법을 찾을 수가 없어서 참 화가나는 상황이었다.

결국, 나는 파일로 우선 저장했다가 사용후 다 지워버리는 방법을 택했다.

위의 코드에서 중요한 점은 response되어 오는 코드가 binary이기 때문에 저장 방식을 wb로 해주어야 한다는 점이다. 그 이외에는 그저 파일을 저장하는 코드이다.

참고로 폴더안의 모든 데이터를 삭제하는 ruby 코드는 다음과 같다.

FileUtils.rm_rf(Dir.glob(Rails.root.join('public', 'upload', '*')))

Share to ...

#ruby
#rails
#line
#api
#message
#content
#binary
#encode