大家好,
希望这里是提问的正确地方。我正在尝试将另一论坛的一组数据导入到我们新的 Discourse 实例中(这是我们希望过渡的内部知识帖子)。
我已将旧数据整理成多个 JSON 结构,但在上传与旧帖子相关的各种图片时遇到了困难。
我使用了 discourse_api gem,目前进展顺利,尽管我也意识到它尚不完整。如果图片托管在某处,我可以成功上传图片,例如:
client.upload_file({'user_id':24,url:'http://valid.url.here/foo.jpg','synchronous':true})
但当我尝试上传位于本地机器上的图片时,却遇到了问题:
client.upload_file({'user_id':24,file:'/local/path/to/image/foo.jpg','synchronous':true})
上述操作返回了以下错误:
DiscourseApi::UnprocessableEntity: {"failed"=>"FAILED",
"message"=>"undefined method 'tempfile' for
#<String:0x00007f409d2fa398>"} from /home/user/.rvm/gems/
ruby-2.3.7/gems/discourse_api-0.36.0/lib/discourse_api/
client.rb:154:in 'handle_error'
我查阅了一些资料,意识到我可能需要对请求进行一些 base64 编码处理,以确保其格式正确(我也意识到,也许 Ruby gem 的上传方法根本无法支持这种类型的上传;如果是这样,那也没关系)。
我主要是想寻求一些指导,看看是否有人遇到过类似的问题,或者我是否完全走错了方向。提前感谢,祝好 
pfaffman
(Jay Pfaffman)
2
除非你有特殊原因无法这样做,否则我建议你查看导入脚本目录,了解使用 JSON 文件的导入器。这比使用 API 更简单。
blake
(Blake Erickson)
3
嗨 Tony,
我同意,使用 API 上传本地文件确实有点棘手。下面的代码应该能解决问题:
# upload_image.rb
require 'discourse_api'
require 'fileutils'
client = DiscourseApi::Client.new("Discourse 站点 URL")
client.api_key = "您的 API 密钥"
client.api_username = "用户名"
filename = ARGV[1] # 文件的完整路径,例如 /home/tony/mypic.png
args = {
:file => Faraday::UploadIO.new(filename, 'image/png')
}
resp = client.upload_file(args)
url = resp['url']
width = resp['width']
height = resp['height']
# topic_id 是您要上传图片到的主题 ID。
args = {
:topic_id => ARGV[0],
:raw => "<img src=\"#{url}\" width=\"#{width}\" height=\"#{height}\">"
}
# 这将在指定的主题中创建一个新帖子
resp = client.create_post(args)
这段代码将使用 Faraday gem 来提供 upload_file 所需的正确文件格式。文件上传后,必须将其分配给某个主题或帖子才能显示,否则它会被自动删除。
您可以这样调用此脚本:
ruby upload_image.rb <topic_id> <filename>
ruby upload_image.rb 128 /home/tony/mypic.png
Blake,
万分感谢。我打算去了解一下 Faraday gem,弄清楚它为我做了什么,然后测试一下你的脚本。真的很感谢你抽出时间!
-tony。
我花了不少时间研究如何从 Python 脚本调用上传端点。我首先遵循建议,通过 Chrome 开发者工具逆向分析上传 API 调用。接着,我通过 Postman 复现了该上传请求。对我来说最耗时的部分是将这些操作转化为可运行的 Python 代码。不知何故,Postman 生成的 Python 代码也无法正常工作。以下是最终对我生效的方法:
requests.post('/uploads.json', files={'files[]': open('/path/to/image.png', 'rb')}, data={'type': 'composer'})