将文档上传到 FSCrawler 以在 Elasticsearch 中建立索引的正确方法
Posted
技术标签:
【中文标题】将文档上传到 FSCrawler 以在 Elasticsearch 中建立索引的正确方法【英文标题】:Proper way to upload a doc to FSCrawler for indexing in Elasticsearch 【发布时间】:2020-05-16 06:54:52 【问题描述】:我正在对 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,它会像 curl
(在命令行上)那样将文件提交给 FSCrawler。
在此示例中,我只是尝试使用 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】:我终于尝试了Faraday,并在this answer的基础上得出了以下结论:
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
请求。这个 sn-p 几乎和 curl 一样发布请求。要通过代理路由此呼叫,我只需将, proxy: 'http://localhost:8866'
添加到连接设置的末尾即可。
【讨论】:
以上是关于将文档上传到 FSCrawler 以在 Elasticsearch 中建立索引的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
如何将 FSCrawler REST 与 docker-compose 连接起来
是否可以使用 FSCrawler 将文件内容插入 Elasticsearch 中现有索引的特定 _id