You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用QuickBooks API上传JPG图片遇500错误及gem调用问题求助

Fixing QuickBooks Online API Upload Errors: 500 Unsupported Content Type & NoMethodError

Hi there! I know you've been troubleshooting this for two days, so let's get straight to fixing your QBO API upload issues.


1. Fixing the 500 "Unsupported Content Type" Error (Direct Signet Request)

The root cause here is that QBO's /upload endpoint requires a multipart/form-data request, but your current code is sending application/json with an incorrectly formatted body. The error message clearly states it can't consume the content type you're sending.

What's Wrong with Your Current Request:

  • You set Content-Type: application/json but added a boundary (which is exclusively for multipart requests)
  • You're only sending the JSON metadata, not including the actual file binary data in the request
  • QBO expects two distinct parts in the multipart request:
    1. A JSON part with the Attachable metadata (like FileName, AttachableRef)
    2. A binary part with the raw file content

Corrected Code:

Here's how to adjust your Signet code to send a valid multipart request:

@client = Signet::OAuth1::Client.new(
  :temporary_credential_uri => "https://oauth.intuit.com/oauth/v1/get_request_token",
  :authorization_uri => "https://appcenter.intuit.com/Connect/Begin",
  :token_credential_uri => "https://oauth.intuit.com/oauth/v1/get_access_token",
  :client_credential_key => App.find_by_name('quickbooks').clientid,
  :client_credential_secret => App.find_by_name('quickbooks').clientsecret
)
@client.token_credential_key = quickbooks.accesstoken
@client.token_credential_secret = quickbooks.refreshtoken
realmid = quickbooks.uid
url = Rails.env.development? ? "sandbox-quickbooks.api.intuit.com" : "quickbooks.api.intuit.com"

# Prepare the metadata JSON
metadata = {
  "AttachableRef": [
    { "EntityRef": { "type": "Invoice", "value": "95" } }
  ],
  "FileName": params[:file].original_filename,
  "ContentType": "image/jpg"
}.to_json

# Generate a unique boundary for multipart formatting
boundary = "----WebKitFormBoundary#{SecureRandom.hex(10)}"

# Build the multipart request body
request_body = [
  "--#{boundary}",
  'Content-Disposition: form-data; name="metadata"',
  'Content-Type: application/json',
  '',
  metadata,
  "--#{boundary}",
  "Content-Disposition: form-data; name=\"file\"; filename=\"#{params[:file].original_filename}\"",
  "Content-Type: image/jpg",
  '',
  params[:file].read,
  "--#{boundary}--",
  ''
].join("\r\n")

# Send the request with correct headers
original_request = [
  'Post',
  "https://#{url}/v3/company/#{realmid}/upload",
  [
    ['Content-Type', "multipart/form-data; boundary=#{boundary}"]
  ],
  request_body
]

response = @client.fetch_protected_resource(:request => original_request)

Key changes:

  • Set Content-Type to multipart/form-data with a valid, unique boundary
  • Included both the metadata JSON and file binary in the request body
  • Followed proper multipart formatting rules with boundary separators

2. Fixing the NoMethodError: undefined method 'post_with_multipart' (quickbook-ruby Gem)

This error occurs because the quickbook-ruby gem expects an OAuth::AccessToken object for the :access_token parameter, but you're passing a plain string. The gem tries to call post_with_multipart on the token, which doesn't exist on a String.

Corrected Code:

First, create a valid OAuth::AccessToken instance using your consumer and token credentials, then pass that to the Upload service:

# Initialize your OAuth consumer with your actual app credentials
OAUTH_CONSUMER_KEY = App.find_by_name('quickbooks').clientid
OAUTH_CONSUMER_SECRET = App.find_by_name('quickbooks').clientsecret

::QB_OAUTH_CONSUMER = OAuth::Consumer.new(
  OAUTH_CONSUMER_KEY, 
  OAUTH_CONSUMER_SECRET, 
  { 
    :site => "https://oauth.intuit.com",
    :request_token_path => "/oauth/v1/get_request_token",
    :authorize_url => "https://appcenter.intuit.com/Connect/Begin",
    :access_token_path => "/oauth/v1/get_access_token"
  }
)

# Create a valid OAuth::AccessToken instance using your stored tokens
access_token = OAuth::AccessToken.new(
  QB_OAUTH_CONSUMER,
  quickbooks.accesstoken, # Your stored access token string
  quickbooks.refreshtoken # Your stored refresh token string
)

# Prepare the Attachable metadata
meta = Quickbooks::Model::Attachable.new
meta.file_name = "monkey.jpg"
meta.note = "A note"
meta.content_type = "image/jpg"
entity = Quickbooks::Model::BaseReference.new(123, type: 'Transfer')
meta.attachable_ref = Quickbooks::Model::AttachableRef.new(entity)

# Initialize the Upload service with the AccessToken object (not a string)
upload_service = Quickbooks::Service::Upload.new(
  :realm_id => quickbooks.uid, # Your actual realm ID
  :access_token => access_token
)

# Upload the file (ensure doc_path is a valid path to your local file)
doc_path = '/path/to/your/monkey.jpg'
result = upload_service.upload(doc_path, meta)

Key fixes:

  • Created a proper OAuth::AccessToken instead of passing a raw string
  • Passed the meta object to upload() (the gem uses this to inject the correct metadata)
  • Used your actual stored realm ID, access token, and refresh token from your quickbooks record

Final Tips:

  • For the gem approach, run bundle update quickbooks-ruby to ensure you're using the latest version
  • Always test in the sandbox environment first before moving to production
  • Double-check that your QBO app has the Attachments scope enabled in the Intuit Developer Portal

内容的提问来源于stack exchange,提问作者naina sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:17:29