Правильный способ загрузки do c в FSCrawler для индексации в Elasticsearch - PullRequest
0 голосов
/ 30 января 2020

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

1 Ответ

0 голосов
/ 31 января 2020

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

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)

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

...