Правильный способ загрузки документа в FSCrawler для индексации в Elasticsearch

Я создаю прототип приложения Rails для загрузки документов в FSCrawler (с запущенным интерфейсом REST) ​​для включения в индекс Elasticsearch. Используя их пример, это работает:

response = `curl -F "file=@#{params[:document][:upload].tempfile.path}" "http://127.0.0.1:8080/fscrawler/_upload?debug=true"`

Файл загружается, и его содержимое индексируется. Это пример того, что я получаю:

"{\n \"ok\" : true,\n \"filename\" : \"RackMultipart20200130-91061-16swulg.pdf\",\n \"url\" : \"http://127.0.0.1:9200/local/_doc/d661edecf3e28572676e97a6f0d1d\",\n \"doc\" : {\n \"content\" : \"\\n \\n \\n\\nBasically, what you need to know is that Dante is all IP-based, and makes use of common IT standards. Each Dante device behaves \\n\\nmuch like any other network device you would already find on your network. \\n\\nIn order to make integration into an existing network easy, here are some of the things that Dante does: \\n\\n▪ Dante...

Когда я бегу curlв командной строке я получаю ВСЕ, например, правильно заданное "имя файла". Если я использую его, как указано выше, в контроллере Rails, как вы можете видеть, в качестве имени файла устанавливается имя файла Tempfile. Это не подходящее решение. Пытаюсь использоватьparams[:document][:upload].tempfile (без .path) или просто params[:document][:upload] оба полностью терпят неудачу.

Я пытаюсь сделать это "правильным способом", но каждое воплощение использования надлежащего HTTP-клиента для этого терпит неудачу. Я не могу понять, как вызвать HTTP POST, который отправит файл в FSCrawler таким образомcurl (в командной строке) делает это.

В этом примере я просто пытаюсь отправить файл с помощью Tempfileфайловый объект. По какой-то причине FSCrawler выдает ошибку в комментарии и получает немного метаданных, но контент не индексируется:

## Failed to extract [100000] characters of text for ...
## org.apache.tika.exception.ZeroByteFileException: InputStream must have > 0 bytes
uri = URI("http://127.0.0.1:8080/fscrawler/_upload?debug=true")
request = Net::HTTP::Post.new(uri)
form_data = [['file', params[:document][:upload].tempfile,
  { filename: params[:document][:upload].original_filename,
  content_type: params[:document][:upload].content_type }]]
request.set_form form_data, 'multipart/form-data'
response = Net::HTTP.start(uri.hostname, uri.port) do |http|
  http.request(request)
end

Если я изменю указанное выше, чтобы использоватьparams[:document][:upload].tempfile.path, то я не получаю сообщение об ошибке InputStream, но я также (все еще) не получаю индексированного содержимого. Это пример того, что я получаю:

 {"_index":"local","_type":"_doc","_id":"72c9ecf2a83440994eb87d28786e6","_version":3,"_seq_no":26,"_primary_term":1,"found":true,"_source":{"content":"/var/folders/bn/pcc1h8p16tl534pw__fdz2sw0000gn/T/RackMultipart20200130-91061-134tcxn.pdf\n","meta":{},"file":{"extension":"pdf","content_type":"text/plain; charset=ISO-8859-1","indexing_date":"2020-01-30T15:33:45.481+0000","filename":"Similarity in Postgres and Rails using Trigrams · pganalyze.pdf"},"path":{"virtual":"Similarity in Postgres and Rails using Trigrams · pganalyze.pdf","real":"Similarity in Postgres and Rails using Trigrams · pganalyze.pdf"}}}

Если я попытаюсь использовать RestClient и попытаюсь отправить файл, указав фактический путь к Tempfile, я получаю это сообщение об ошибке и ничего не получаю:

## Unsupported media type
response = RestClient.post 'http://127.0.0.1:8080/fscrawler/_upload?debug=true',
  file: params[:document][:upload].tempfile.path,
  content_type: params[:document][:upload].content_type

Если я попытаюсь .read() файл и отправляю его, затем я нарушаю форму FSCrawler:

## Internal server error
request = RestClient::Request.new(
  :method => :post,
  :url => 'http://127.0.0.1:8080/fscrawler/_upload?debug=true',
  :payload => {
    :multipart => true,
    :file => File.read(params[:document][:upload].tempfile),
    :content_type => params[:document][:upload].content_type
})
response = request.execute

Очевидно, я пробовал это всеми доступными способами, но я не могу curlработает с любыми известными HTTP-клиентами на основе Ruby. Я совершенно не понимаю, как заставить Ruby отправлять данные в FSCrawler таким образом, чтобы содержимое документа было правильно проиндексировано. Я занимаюсь этим гораздо дольше, чем могу признаться. Что мне здесь не хватает?

1 ответ

Решение

Я наконец попробовал Фарадея и, основываясь на этом ответе, пришел к следующему:

connection = Faraday.new('http://127.0.0.1:8080') do |f|
  f.request :multipart
  f.request :url_encoded
  f.adapter :net_http
end
file = Faraday::UploadIO.new(
  params[:document][:upload].tempfile.path,
  params[:document][:upload].content_type,
  params[:document][:upload].original_filename
)
payload = { :file => file }
response = connection.post('/fscrawler/_upload', payload)

Использование Fiddler помогло мне увидеть результаты моих попыток, поскольку я все ближе и ближе подходил кcurlзапрос. Этот фрагмент отправляет запрос почти так же, как и curl. Чтобы направить этот вызов через прокси, мне просто нужно было добавить, proxy: 'http://localhost:8866' до конца настройки подключения.

Другие вопросы по тегам