+ Start a Discussion
juventussjuventuss 

Attaching a file to salesforce via the API

Could someone point me or possibly paste a sample of how to convert a file to base64 and upload to an opportunity under salesforce.com.

I've looked though previous questions in regards to this issue and most of them are quite old. Thank you
DevAngelDevAngel

Hi juventuss,

There is an example of how to do this in the Sforce Explorer available here:

http://prdownloads.sourceforge.net/sforce/sforceExplorerSetup.zip?download

juventussjuventuss
hello Dave,

I downloaded the sample but i cant seem to figure out how it uploads a file. all i can do is select a file for download or for opening.
DevAngelDevAngel

Hi juventuss,

This is the function that uploads the document.  As you can see from the code, you simply open the document for reading and read the document into a byte array.  You then set the value of the body property of the document object to the byte array.  Set a couple of other simple properties like name and keywords and send the document object in a create call.

Private Sub CreateDocument(ByVal docPath As String)

Dim doc As New sforce.Document

Dim fi As System.IO.FileInfo = New System.IO.FileInfo(docPath)

If fi.Length > 5000000 Then

System.Windows.Forms.MessageBox.Show("This file is too big. The maximum document size is 5 MB.", "Document Error", MessageBoxButtons.OK, MessageBoxIcon.Error)

Else

doc.Name = fi.Name

doc.Description = fi.FullName

doc.FolderId = CType(Me.cboFolders.SelectedItem, ComboFolderItem).Folder.Id

Dim fs As System.IO.FileStream = System.IO.File.OpenRead(docPath)

Dim buffer() As Byte

ReDim buffer(Convert.ToInt32(fi.Length))

fs.Read(buffer, 0, buffer.Length)

doc.Body = buffer

Dim sr As sforce.SaveResult = binding.create(New sforce.sObject() {doc})(0)

If sr.success Then

Me.LoadDocs(doc.FolderId)

Else

MessageBox.Show("There was an error creating the document." & System.Environment.NewLine + System.Environment.NewLine + "Message: " + sr.errors(0).message)

End If

End If

End Sub

GoldwindGoldwind

Hi,

I need to use an attachment also. I look at the sample and saw a definition which i cant do with my web service:

Dim Attach As New sforce.Attachment

This a compilation error since sforce doesnt have the "Attachment" object.

I"m using the partner wsdl and adding Contacts using Xml

How can i add an attachment using the partner wsdl?

 

Thanks

DevAngelDevAngel
First in VB .NET:
 
Shared Sub button3_Click(ByVal sender As Object, ByVal e As System.EventArgs)
   Dim binding As sforceP.SforceService = New sforceP.SforceService
   Dim lr As sforceP.LoginResult = binding.login("username", "password")
   binding.SessionHeaderValue = New sforceP.SessionHeader
   binding.SessionHeaderValue.sessionId = lr.sessionId
   binding.Url = lr.serverUrl
   Dim OFD As New System.Windows.Forms.OpenFileDialog
 
   Dim doc As sforceP.sObject = New sforceP.sObject
   If OFD.ShowDialog().Equals(DialogResult.OK) Then
      Dim fi As System.IO.FileInfo = New System.IO.FileInfo(OFD.FileName)
      If fi.Length > 5000000 Then
         System.Windows.Forms.MessageBox.Show("This file is too big. The maximum document size is 5 MB.", "Document Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
         Dim xmlDoc As System.Xml.XmlDocument = New System.Xml.XmlDocument
         Dim any(4) As System.Xml.XmlElement
         doc.Any = any
         doc.Any(0) = xmlDoc.CreateElement("Name")
         doc.Any(0).InnerText = fi.Name
         doc.Any(1) = xmlDoc.CreateElement("Description")
         doc.Any(1).InnerText = fi.FullName
         doc.Any(2) = xmlDoc.CreateElement("FolderId")
         doc.Any(2).InnerText = "00l30000000ePKd"
         doc.type = "Document"
 
         Dim fs As System.IO.FileStream = System.IO.File.OpenRead(OFD.FileName)
         Dim buffer(Convert.ToInt32(fi.Length)) As Byte
         fs.Read(buffer, 0, buffer.Length)
         doc.Any(3) = xmlDoc.CreateElement("Body")
         doc.Any(3).InnerText = Convert.ToBase64String(buffer)
         Dim sr As sforceP.SaveResult = binding.create(New sforceP.sObject() {doc})(0)
         If (sr.success) Then
            MessageBox.Show("Successfully create the document.")
Else
            MessageBox.Show("There was an error creating the document." + System.Environment.NewLine + System.Environment.NewLine + "Message: " + sr.errors(0).message)
End If
 
'We can do a similar thing for an attachment
         Dim attach As sforceP.sObject = New sforceP.sObject
         attach.type = "Attachment"
         attach.Any = any
 
         attach.Any(0) = xmlDoc.CreateElement("Name")
         attach.Any(0).InnerText = fi.Name
         attach.Any(1) = xmlDoc.CreateElement("IsPrivate")
         attach.Any(1).InnerText = "false"
         attach.Any(2) = xmlDoc.CreateElement("ParentId")
         attach.Any(2).InnerText = "00130000000iEjv"
         attach.Any(3) = xmlDoc.CreateElement("Body")
         attach.Any(3).InnerText = Convert.ToBase64String(buffer)
 
         sr = binding.create(New sforceP.sObject() {attach})(0)
         If (sr.success) Then
            MessageBox.Show("Successfully create the attachment on an account.")
Else
            MessageBox.Show("There was an error creating the attachment." + System.Environment.NewLine + System.Environment.NewLine + "Message: " + sr.errors(0).message)
End If
End If
   End If
End Sub


 

DevAngelDevAngel

Now, in C#


private void button3_Click(object sender, System.EventArgs e)
{
      sforceP.SforceService binding = new sforceP.SforceService();
      sforceP.LoginResult lr = binding.login("username", "paassword");
      binding.SessionHeaderValue = new sforceP.SessionHeader();
      binding.SessionHeaderValue.sessionId = lr.sessionId;
      binding.Url = lr.serverUrl;
 
      sforceP.sObject doc = new sforceP.sObject();
      if (this.OFD.ShowDialog().Equals(DialogResult.OK))
      {
            System.IO.FileInfo fi = new System.IO.FileInfo(OFD.FileName);
            if (fi.Length > 5000000)
            {
                  System.Windows.Forms.MessageBox.Show("This file is too big. The maximum document size is 5 MB.", "Document Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }    
else
            {
                  System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
                  doc.Any = new System.Xml.XmlElement[4];
                  doc.Any[0] = xmlDoc.CreateElement("Name");
                  doc.Any[0].InnerText = fi.Name;
                  doc.Any[1] = xmlDoc.CreateElement("Description");
                  doc.Any[1].InnerText = fi.FullName;
                  doc.Any[2] = xmlDoc.CreateElement("FolderId");
                  doc.Any[2].InnerText = "00l30000000ePKd";
                  doc.type = "Document";
 
                  System.IO.FileStream fs = System.IO.File.OpenRead(OFD.FileName);
                  byte[] buffer = new byte[fi.Length];
                  fs.Read(buffer, 0, buffer.Length);
                  doc.Any[3] = xmlDoc.CreateElement("Body");
                  doc.Any[3].InnerText = Convert.ToBase64String(buffer);
                  sforceP.SaveResult sr = binding.create(new sforceP.sObject[] {doc})[0];
                  if (sr.success)
                  {
                        MessageBox.Show("Successfully create the document.");
                  }
else
                  {
                        MessageBox.Show("There was an error creating the document." + System.Environment.NewLine + System.Environment.NewLine + "Message: " + sr.errors[0].message);
                  }
 
//We can do a similar thing for an attachment
                  sforceP.sObject attach = new sforceP.sObject();
                  attach.type = "Attachment";
                  attach.Any = new System.Xml.XmlElement[4];
 
                  attach.Any[0] = xmlDoc.CreateElement("Name");
                  attach.Any[0].InnerText = fi.Name;
                  attach.Any[1] = xmlDoc.CreateElement("IsPrivate");
                  attach.Any[1].InnerText = "false";
                  attach.Any[2] = xmlDoc.CreateElement("ParentId");
                  attach.Any[2].InnerText = "00130000000iEjv";
                  attach.Any[3] = xmlDoc.CreateElement("Body");
                  attach.Any[3].InnerText = Convert.ToBase64String(buffer);
 
                  sr = binding.create(new sforceP.sObject[] {attach})[0];
                  if (sr.success)
                  {
                        MessageBox.Show("Successfully create the attachment on an account.");
                  }
else
                  {
                        MessageBox.Show("There was an error creating the attachment." + System.Environment.NewLine + System.Environment.NewLine + "Message: " + sr.errors[0].message);
                  }
 
            }
      }
}


 

juventussjuventuss
thanks for the help so far.

I tried using part of the code but i keep getting an error on these lines.

Dim doc as sforce.object = new sforce.object (ERROR:Ne cannot be used on a class that is declared "MustInherit')

doc.any = any
doc.Any(0) = xmlDoc.CreateElement("Name")
doc.Any(0).InnerText = fi.Name
doc.Any(1) = xmlDoc.CreateElement("Description")
doc.Any(1).InnerText = fi.FullName
doc.Any(2) = xmlDoc.CreateElement("FolderId")
doc.Any(2).InnerText = "00l30000000ePKd"
doc.type = "Document"
(ERROR: Any is not a member of 'Saleforce_conector.sforce.sobject')

is there an import,include that i'm missing ?

Thank you.
DevAngelDevAngel

Hi juventuss,

Is your intellisense not working?????

Dim doc as sforce.sObject = new sforce.sObject

 

Notice that is is sObject not object!

juventussjuventuss
My intellisense is working and i have sforce.sobject.
DevAngelDevAngel
Ok, then, did you correct your code that you posted and if so is it compiling now?
juventussjuventuss
I am still unable to get it sorted out. The samples provided arent helping. All I want to do is upload a file to a predetermined opportunity.
GlennWGlennW
Try this:

Add these two functions to your project. (It's in VB I'll send you the C# if you like)

You will have to change the name of the global object: GlobalSforce to the name of your sforce50 object. Just call the function with the ID of the Opportunity, the complete file name of the string and the name of the attachment.

Cheers;
GlennW



Public Function loadAttachement(ByVal id As String, ByVal filename As String, ByVal showName As String) As Boolean
Dim xdoc As New Xml.XmlDocument
Dim updateFields() As Xml.XmlElement
Dim updateObject As Sforce30.sObject
Dim updateObjects(0) As Sforce30.sObject
Dim sfResults() As Sforce30.SaveResult
Dim idx As Integer
Dim fileInfo As System.IO.FileInfo

fileInfo = New System.IO.FileInfo(filename)

ReDim Preserve updateFields(2)

updateFields(0) = xdoc.CreateElement("ParentId")
updateFields(0).InnerText = id

updateFields(1) = xdoc.CreateElement("Name")
updateFields(1).InnerText = showName

updateFields(2) = xdoc.CreateElement("Body")
updateFields(2).InnerText = getFileBase64String(filename)

updateObject = New Sforce30.sObject
updateObject.type = "Attachment"
updateObject.Any = updateFields
updateObjects(0) = updateObject

Try
sfResults = globalSForce.create(updateObjects)
Catch soapEx As System.Web.Services.Protocols.SoapException
Return False
Catch ex As Exception
Return False
End Try
Return True
End Function

Private Function getFileBase64String(ByVal objFileName As String) As String
Dim inFile As System.IO.FileStream
Dim binaryData() As Byte
Dim bytesRead As Long
Dim base64String As String = ""

inFile = New System.IO.FileStream(objFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)
ReDim binaryData(inFile.Length)
bytesRead = inFile.Read(binaryData, 0, inFile.Length)
inFile.Close()

base64String = System.Convert.ToBase64String(binaryData, 0, binaryData.Length)

Return base64String
End Function
juventussjuventuss
Glen,

I added that code in but i get an error here

updateObject = New sforce.sObject 'New' cannot be used on a class that is declared 'MustInherit'
updateObject.type = "Attachment" 'type' is not a member of 'salesforce_connector.sforce.sObject'
updateObject.Any = updateFields
updateObjects(0) = updateObject


Thanks for your assistance thus far.
SuperfellSuperfell
sounds like you imported the enterprise WSDL but are trying to write Partner WSDL code.
juventussjuventuss
i downloaded the WSDL provided by the salesforce admin. How do i rectify this issue ?
SuperfellSuperfell
There are 2 WSDL's, Enterprise WSDL and Partner WSDL, ask the admin for the Partner WSDL or download the Partner WSDL from a developer edition account. (The partner WSDL is identical for all organizations)
juventussjuventuss
That fixed it. Thank you so very much...
I knew it was going to be an easy fix. ahhh..
juventussjuventuss
Maybe i spoke too soon. I tried uploading a file and while i do not get any error or prompts, the files are not showing up in their respective opportunities.

Here is my code
Thanks for the help so far

Public Function loadAttachement(ByVal id As String, ByVal filename As String, ByVal showName As String) As Boolean
Dim xdoc As New Xml.XmlDocument
Dim updateFields() As Xml.XmlElement
Dim binding As sforce1.SforceService = New sforce1.SforceService
Dim updateObject As sforce1.sObject
Dim updateObjects(0) As sforce1.sObject
Dim sfResults() As sforce1.SaveResult
Dim idx As Integer
Dim fileInfo As System.IO.FileInfo

fileInfo = New System.IO.FileInfo(filename)
If fileInfo.Length > 5000000 Then
System.Windows.Forms.MessageBox.Show("This file is too big. The maximum document size is 5 MB.", "Document Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
ReDim Preserve updateFields(2)

updateFields(0) = xdoc.CreateElement("ParentId")
updateFields(0).InnerText = id

updateFields(1) = xdoc.CreateElement("Name")
updateFields(1).InnerText = fileInfo.Name

updateFields(2) = xdoc.CreateElement("Body")
updateFields(2).InnerText = getFileBase64String(filename)

updateObject = New sforce1.sObject
updateObject.type = "Attachment"
updateObject.Any = updateFields
updateObjects(0) = updateObject
Try
sfResults = binding.create(updateObjects)

Catch soapEx As System.Web.Services.Protocols.SoapException
Return False
Catch ex As Exception
Return False
End Try
Return True
End If
End Function
juventussjuventuss
any suggestions ?
SuperfellSuperfell
The result from create includes a flag that indicates if the create succeeded, and an error collection in the case that it didn't, you need to check these to see why the create call failed.
juventussjuventuss


SimonF wrote:
The result from create includes a flag that indicates if the create succeeded, and an error collection in the case that it didn't, you need to check these to see why the create call failed.




The flag indicates nothing. I look at my network traffic and packets are moving though but nothing gets attached. Quite confusing.
SuperfellSuperfell
So the success flag is true and there's nothing in the error's collection?
juventussjuventuss
yes. No error message is thrown.
SuperfellSuperfell
Note, that no error is thrown, the return value is a status object, this status object can contain the details of why the create failed.

Can you post your finalized code ?
juventussjuventuss
This is the code i presently have


Public Function loadAttachement(ByVal id As String, ByVal filename As String, ByVal showName As String) As Boolean
Dim xdoc As New Xml.XmlDocument
Dim updateFields() As Xml.XmlElement
Dim binding As sforce1.SforceService = New sforce1.SforceService
Dim updateObject As sforce1.sObject
Dim updateObjects(0) As sforce1.sObject
Dim sfResults() As sforce1.SaveResult
Dim idx As Integer
Dim fileInfo As System.IO.FileInfo

fileInfo = New System.IO.FileInfo(filename)
If fileInfo.Length > 5000000 Then
System.Windows.Forms.MessageBox.Show("This file is too big. The maximum document size is 5 MB.", "Document Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
ReDim Preserve updateFields(2)

updateFields(0) = xdoc.CreateElement("ParentId")
updateFields(0).InnerText = id

updateFields(1) = xdoc.CreateElement("Name")
updateFields(1).InnerText = fileInfo.Name

updateFields(2) = xdoc.CreateElement("Body")
updateFields(2).InnerText = getFileBase64String(filename)

updateObject = New sforce1.sObject
updateObject.type = "Attachment"
updateObject.Any = updateFields
updateObjects(0) = updateObject
Try
frmwksheet.DefInstance.lblsaveinfo.Visible = True
frmwksheet.DefInstance.lblsaveinfo.Text = "Saving to salesforce"
sfResults = binding.create(updateObjects)
frmwksheet.DefInstance.lblsaveinfo.Visible = False

Catch soapEx As System.Web.Services.Protocols.SoapException
Return False
Catch ex As Exception
Return False
End Try
Return True
End If
End Function

Private Function getFileBase64String(ByVal objFileName As String) As String
Dim inFile As System.IO.FileStream
Dim binaryData() As Byte
Dim bytesRead As Long
Dim base64String As String = ""

inFile = New System.IO.FileStream(objFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)
ReDim binaryData(inFile.Length)
bytesRead = inFile.Read(binaryData, 0, inFile.Length)
inFile.Close()

base64String = System.Convert.ToBase64String(binaryData, 0, binaryData.Length)

Return base64String
End Function
SuperfellSuperfell
I can't see where you code is checking the properties on the SaveResults array (sfResults) like i said earlier. You need to add soemthing like

if not sfResults[0].success then
throw new Exception(sfResults[0].Errors[0].Message);
end if

It might be worth your while to work through the samples in the docs.
juventussjuventuss
I now get this error.

An unhandled exception of type 'System.Net.WebException' occurred in system.web.services.dll

Additional information: The underlying connection was closed: An unexpected error occurred on a receive.

This is the code i have.



Dim binding As sforce1.SforceService = New sforce1.SforceService
binding.SessionHeaderValue = New sforce1.SessionHeader
binding.SessionHeaderValue.sessionId = frmlogin.DefInstance.lblsession.Text
binding.Url = "http://na1.salesforce.com/services/Soap/u/5.0"
Dim fileInfo As System.IO.FileInfo
Dim OFD As New System.Windows.Forms.OpenFileDialog
Dim sr As sforce1.SaveResult

If OFD.ShowDialog().Equals(DialogResult.OK) Then
Dim fi As System.IO.FileInfo = New System.IO.FileInfo(filename)
fileInfo = New System.IO.FileInfo(filename)
If fileInfo.Length > 5000000 Then
System.Windows.Forms.MessageBox.Show("This file is too big. The maximum document size is 5 MB.", "Document Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
Dim fs As System.IO.FileStream = System.IO.File.OpenRead(filename)
Dim buffer(Convert.ToInt32(fi.Length)) As Byte
fs.Read(buffer, 0, buffer.Length)
Dim xmlDoc As System.Xml.XmlDocument = New System.Xml.XmlDocument
Dim any(4) As System.Xml.XmlElement
Dim attach As sforce1.sObject = New sforce1.sObject
attach.type = "Attachment"
attach.Any = any

attach.Any(0) = xmlDoc.CreateElement("Name")
attach.Any(0).InnerText = fi.Name
attach.Any(1) = xmlDoc.CreateElement("IsPrivate")
attach.Any(1).InnerText = "false"
attach.Any(2) = xmlDoc.CreateElement("ParentId")
attach.Any(2).InnerText = id
attach.Any(3) = xmlDoc.CreateElement("Body")
attach.Any(3).InnerText = Convert.ToBase64String(buffer)
sr = binding.create(New sforce1.sObject() {attach})(0)
If (sr.success) Then
MessageBox.Show("Successfully create the attachment on an account.")
Else
MessageBox.Show("There was an error creating the attachment." + System.Environment.NewLine + System.Environment.NewLine + "Message: " + sr.errors(0).message)
End If
End If
End If
juventussjuventuss
Blah.... Alas it is an issue with the proxy server or firewall. Does salesforce use any port other than 443, 80 to transfer files ?

seems http and https are used randomly to transfer files
SuperfellSuperfell
Its always HTTPS unless you've written code to specifically change it to HTTP.
SrivastavaSrivastava

Hi can i get an C# code for uploading the attachment. I am a newbie and i haven't worked on VB at all

SetoSeto

Hi Juventuss.

 

That's very nice of you to share the code.

U

nfortunately, I am not a programmer, so I don't know what to do with the code alone.
Can you give me also the instructions on how to make this code work?

Vinit Kulkarni 6Vinit Kulkarni 6
I was able to fetch body of the docx file in InnerText of Any object saved in Salesforce documents using partner wsdl from C#.
Now the problem I am facing is, I am not able to parse and save the InnerText as docx file and save it locally. :(
Can someone guide me how to decode the InnerText content and save it as docx file from C#.
            string SOQL = "SELECT Id, Name, Body FROM Document where Id = '" + id + "'";

            QueryResult queryResult = SfdcBinding.query(SOQL);
            
           // below line not working. Tried other encodings also but no success.
            byte[] filebytes = Encoding.ASCII.GetBytes(queryResult.records[0].Any[2].InnerText);  
            File.WriteAllBytes(localfilepath, filebytes);
FirstName LastName 45FirstName LastName 45
Can anybody give example on PHP?