【问题标题】:Upload PDF from Python as attachment to Salesforce Object从 Python 将 PDF 作为附件上传到 Salesforce 对象
【发布时间】:2020-02-19 16:28:38
【问题描述】:

我正在尝试使用 simple_salesforce Python 包将 Python 生成的 pdf 作为附件上传到 salesforce 对象。我尝试了几种不同的方法来实现这一点,但到目前为止还没有运气。这是代码

import base64
import json
from simple_salesforce import Salesforce

instance = ''
sessionId = sf.session_id

def pdf_encode(pdf_filename):
    body = open(pdf_filename, 'rb') #open binary file in read mode 
    body = body.read() 
    body = base64.encodebytes(body)

body = pdf_encode('PDF_Report.pdf')


response = requests.post('https://%s.salesforce.com/services/data/v29.0/sobjects/Attachment/' % instance,
    headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer %s' % sessionId },
    data = json.dumps({
        'ParentId': parent_id,
        'Name': 'test.txt',
        'body': body
    })
)

我收到此错误。

TypeError: Object of type bytes is not JSON serializable

我也试过用

body = base64.encodebytes(body).decode('ascii')

在我的代码中,但我也无法让它工作。我收到错误

UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)

关于如何使用 simple_salesforce 将 Python 3 中的 PDF 作为附件上传到 Salesforce 有什么建议吗?

【问题讨论】:

  • 我没有对该错误的解释,但我通过base64.b64encode(my_file.read()).decode('utf-8') 有一个类似的过程可以正常工作。
  • 嗨大卫 - 感谢您的建议。我尝试使用该代码但得到第二个错误UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)

标签: python python-3.x pdf salesforce simple-salesforce


【解决方案1】:

我正在处理这个问题,并找到了一些上传文件的资源。我使用它为自己创建了一个。

以下是可用于 Python 并将文件上传到 Salesforce 的代码。

import requests
import base64
import json


params = {
    "grant_type": "password",
    "client_id": "Your_Client_Id",
    "client_secret": "Your_Client_Secret",
    "username": "YOUR_EMAIL@procureanalytics.com.pcsandbox", # The email you use to login
    "password": "YOUR_PASSWORD+YOUR_SECURITY_TOKEN" # Concat your password and your security token
}
r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)
# if you connect to a Sandbox, use test.salesforce.com instead
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
print("Access Token:", access_token)
print("Instance URL", instance_url)

#######################################################################################
# Helper function
#######################################################################################
def sf_api_call(action, parameters = {}, method = 'get', data = {}):
    """
    Helper function to make calls to Salesforce REST API.
    Parameters: action (the URL), URL params, method (get, post or patch), data for POST/PATCH.
    """
    headers = {
        'Content-type': 'application/json',
        'Accept-Encoding': 'gzip',
        'Authorization': 'Bearer %s' % access_token
    }
    if method == 'get':
        r = requests.request(method, instance_url+action, headers=headers, params=parameters, timeout=30)
    elif method in ['post', 'patch']:
        r = requests.request(method, instance_url+action, headers=headers, json=data, params=parameters, timeout=10)
    else:
        # other methods not implemented in this example
        raise ValueError('Method should be get or post or patch.')
    print('Debug: API %s call: %s' % (method, r.url) )
    if r.status_code < 300:
        if method=='patch':
            return None
        else:
            return r.json()
    else:
        raise Exception('API error when calling %s : %s' % (r.url, r.content))
        
# Test connection
print(json.dumps(sf_api_call('/services/data/v40.0/query/', {
    'q': 'SELECT Account.Name, Name, CloseDate from Opportunity where IsClosed = False order by CloseDate ASC LIMIT 1'
}), indent=2))

#######################################################################################
# File Upload from directory
#######################################################################################
# 1) Create a ContentVersion
path = "Folder_name\Sample_pdf.pdf"
with open(path, "rb") as f:
    encoded_string = base64.b64encode(f.read()).decode("utf-8")

ContentVersion = sf_api_call('/services/data/v40.0/sobjects/ContentVersion', method="post", data={
    'Title': 'Sample_pdf file',
    'PathOnClient': path,
    'VersionData': encoded_string,
})
ContentVersion_id = ContentVersion.get('id')

# 2) Get the ContentDocument id
ContentVersion = sf_api_call('/services/data/v40.0/sobjects/ContentVersion/%s' % ContentVersion_id)
ContentDocument_id = ContentVersion.get('ContentDocumentId')


# 3) Create a ContentDocumentLink
Id = "Abcd123" # This Id can be anything: Account_Id or Lead_Id or Opportunity_Id
ContentDocumentLink = sf_api_call('/services/data/v40.0/sobjects/ContentDocumentLink', method = 'post', data={
        'ContentDocumentId': ContentDocument_id,
        'LinkedEntityId': Id,
        'ShareType': 'V'
    })

如何使用

第 1 步:

在此处输入您的电子邮件地址和密码。请注意,这里的密码是“您的密码”和您的“安全令牌”的字符串。

# Import libraries
import requests
import base64
import json

params = {
    "grant_type": "password",
    "client_id": "Your_Client_Id",
    "client_secret": "Your_Client_Secret",
    "username": "YOUR_EMAIL@procureanalytics.com.pcsandbox", # The email you use to login
    "password": "YOUR_PASSWORD+YOUR_SECURITY_TOKEN" # Concat your password and your security token
}
r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)
# if you connect to a Sandbox, use test.salesforce.com instead
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
print("Access Token:", access_token)
print("Instance URL", instance_url)

您可以通过帐户>>设置>>重置我的安全令牌在 Salesforce 上获取您的安全令牌。 您将收到一封来自 Salesforce 的电子邮件,其中包含您的安全令牌。

第 2 步:

为 request.post 选择适当的链接
对于沙盒环境:

r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)

对于生产环境:

r = requests.post("https://login.salesforce.com/services/oauth2/token", params=params)

初始连接准备就绪后,第二个单元格的输出应如下所示:

Access Token: !2864b793dbce2ad32c1ba7d71009ec84.b793dbce2ad32c1ba7d71009ec84
Instance URL https://your_company_name--pcsandbox.my.salesforce.com

第三步:

在“从目录上传文件”单元格(单元格 #5)下,指定您的文件路径。 就我而言,这是

# 1) Create a ContentVersion
path = "Folder_name\Sample_pdf.pdf"
with open(path, "rb") as f:
    encoded_string = base64.b64encode(f.read()).decode("utf-8")

第四步:

在同一单元格下,提及您要上传文件的 ID。 下面的示例代码正在为具有 ID 的帐户上传 Accounts 对象上的文件:Abcd123

# 3) Create a ContentDocumentLink
Id = "Abcd123" # This Id can be anything: Account_Id or Lead_Id or Opportunity_Id
ContentDocumentLink = sf_api_call('/services/data/v40.0/sobjects/ContentDocumentLink', method = 'post', data={
        'ContentDocumentId': ContentDocument_id,
        'LinkedEntityId': Id,
        'ShareType': 'V'
    })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    • 2013-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多