我正在对 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
(without .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
如果我将上面的内容更改为 use 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 提交数据。我在这方面的时间比我愿意承认的要长得多。我在这里想念什么?