はじめに
hkob の雑記録の第164回目は、NotionRubyMapping 1.0.0 の公開と、昨日作成した single_file_upload の実装の修正について解説します。
NotionRubyMapping 1.0.0 の公開
まだ File Upload API の更新中ですが、この開発をしているマシンで、NotionRubyMapping が動作しなくなっていました。開発のために Faraday 2.13.1 の gem が入っていたため、こちらが読み込まれてしまい、Faraday 2 系列で動作しない FaradayMiddleware が読み込まれないためでした。別のツールで Faraday 2 がインストールされてしまうこともあると思うので、早急に File Upload API が含まれない Faraday 2.13.1 対応の NotionRubyMapping 1.0.0 をリリースしました。
FileUploadObject#single_file_upload の修正
また、require_relative で notion_ruby_mapping を読み出し、 FileUploadObject.new を実行してみました。すると、以下のようなエラーが出てきました。画像・動画・音声・PDF など様々なファイルがアップロードされるので、Content-Type を octet-stream にしていたのですが、Notion API 側が Content-Type でフィルタしているようです。
/Users/hkob/Library/CloudStorage/Dropbox/ruby/notion_ruby_mapping/lib/notion_ruby_mapping/objects/file_upload_object.rb:35:in 'FileUploadObject#single_file_upload': File upload failed: {object: "error", status: 400, code: "validation_error", message: "File upload has an invalid or unsupported content type of `application/octet-stream`.", request_id: "3102ade0-a5fd-4a90-9a36-448552c18a94"} (StandardError)
スクリプトでは以下のように実行していました。こちらの場合、Content-Type は curl が準備してくれていたのだと思います。
curl --request POST \ --url 'https://api.notion.com/v1/file_uploads/20cd8e4e-98ab-81aa-973b-00b23083c115/send' \ -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \ -H 'Notion-Version: 2022-06-28' \ -H 'Content-Type: multipart/form-data' \ -F "file=@ErSxuLeq.png-medium.png"
mime-types の追加
Content-Type を準備するために mime-types gem をインストールします。 notion_ruby_mapping.gemspec に mime-types を依存関係で追加しました。
spec.add_dependency "faraday" spec.add_dependency "faraday-multipart" spec.add_dependency "mime-types"
さらに、 notion_cache.rb に mime/types の読み込みを追加します。
# frozen_string_literal: true require "singleton" require "faraday" require "faraday/multipart" require "mime/types" module NotionRubyMapping # singleton class of caching Notion objects class NotionCache include Singleton
NotionCache#multipart_request の修正
multipart_request で octet-stream に決め打ちしていた、content-type を MIME::Types#type_for でファイル名から取得できるようにしました。
# @param [String] path # @param [Hash] json # @param [String] fname # @return [Hash] response hash def multipart_request(path, json, fname) raise "Please call `NotionRubyMapping.configure' before using other methods" unless @notion_token content_type = MIME::Types.type_for(fname).first.to_s sleep @wait json_part = Faraday::Multipart::ParamPart.new(json.to_json, "application/json") file_part = Faraday::Multipart::FilePart.new(fname, content_type, File.basename(fname)) p multipart_client response = multipart_client.send(:post) do |request| request.headers["Authorization"] = "Bearer #{@notion_token}" request.headers["content-Type"] = "multipart/form-data" request.path = path request.body = {json: json_part, file: file_part} end p response.body if @debug response.body end
この修正をしたところ、無事に FileUploadObject が無事に作成できました。
おわりに
とりあえず動くことは確認できたので、再度 multipart のテストができるかを試してみます。