Three-stage Upload of Attachments to a Part
You can upload attachments to a part in three stages. To upload attachments to a part, you must set the Part Management > Attachments on parts preference to Yes in the Preference Management utility in Windchill.
You can upload three different types of attachments to a part:
Local file
Link or URL
External storage
* 
Although Security Labels cannot be specified in the content upload using the WRS Product Management domain, all security label constraints for file vaulting are respected for WRS.
Example: Uploading Local Files to a Part
This example demonstrates how to upload three local file attachments to a specific part.
Stage #1— Specify the number of files to attach in the request body. Use the following POST URI with the request body:
URI
POST /Windchill/servlet/odata/ProdMgmt/Parts('OR:wt.part.WTPart:280560')/PTC.ProdMgmt.UploadStage1Action
Request Headers
Content-Type: application/json
CSRF_NONCE: <Use the value from Fetch NONCE example>
Request Body
{
"noOfFiles": 3
}
Stage #1— Sample Response
{
"@odata.context": "$metadata#CacheDescriptor",
"value": [
{
"FileNames": [
76030,
76031,
76032
],
"FolderId": 150329,
"ID": null,
"MasterUrl": "https://windchill.ptc.com/Windchill/servlet/WindchillGW",
"ReplicaUrl": "https://windchill.ptc.com/Windchill/servlet/WindchillGW/wt.fv.uploadtocache.DoUploadToCache_Server/doUploadToChache_Master?mk=wt.fv.uploadtocache.DoUploadToCache_Server&VaultId=150301&FolderId=150329&CheckSum=456186&sT=1507542170&sign=Ca4ouGGOZiopnqbd4mbUVg%3D%3D&site=https%3A%2F%2Fwindchill.ptc.com%2FWindchill%2Fservlet%2FWindchillGW&AUTH_CODE=HmacMD5&isProxy=true&delegate=wt.fv.uploadtocache.DefaultRestFormGeneratorDelegate",
"StreamIds": [
76030,
76031,
76032
],
"VaultId": 150301
}
],
"@PTC.AppliedContainerContext.LocalTimeZone": "America/New_York"
}
Stage #2— Copy the value of ReplicaUrl from the Stage #1 response and use it in the POST URI of Stage #2.
* 
Ensure that the request body maintains the sequence of multi-part entities.
Use the following POST URI with the request body:
URI
POST /Windchill/servlet/WindchillGW/wt.fv.uploadtocache.DoUploadToCache_Server/doUploadToChache_Master?mk=wt.fv.uploadtocache.DoUploadToCache_Server&VaultId=150301&FolderId=150329&CheckSum=456186&sT=1507542170&sign=Ca4ouGGOZiopnqbd4mbUVg%3D%3D&site=https%3A%2F%2Fwindchill.ptc.com%2FWindchill%2Fservlet%2FWindchillGW&AUTH_CODE=HmacMD5&isProxy=true&delegate=wt.fv.uploadtocache.DefaultRestFormGeneratorDelegate
Request Headers
Content-Type: multipart/form-data; boundary=-----------------------------boundary
Request Body
-----------------------------boundary
Content-Disposition: form-data; name="Master_URL"
https://windchill.ptc.com/Windchill/servlet/WindchillGW
----------------------------boundary
Content-Disposition: form-data; name="CacheDescriptor_array"
76030: 76030: 76030; 76031: 76031: 76031; 76032: 76032: 76032;
----------------------------boundary
Content-Disposition: form-data; name="76030"; filename="TestFile1.txt"
is content of test file 1.
----------------------------boundary
Content-Disposition: form-data; name="76031"; filename="TestFile2.txt"
is content of test file 2.
----------------------------boundary
Content-Disposition: form-data; name="76032"; filename="TestFile3.txt"
is content of test file 3.
----------------------------boundary
* 
The CacheDescriptor_array contains the following information <streamId>:<fileName>:<contentId>:<fileSize> where,
streamId—Specifies the unique content ID from the Stage #1 response.
fileName—Specifies the name of the file from the Stage #1 response.
contentId—Same as streamId.
fileSize—Specifies the size of the file to be uploaded in bytes (optional).
The Stage #2 response contains information about streamId, fileSize, and encodedInfo for each file to be uploaded. This information is used in Stage #3 for uploading each file attachment to the part.
Stage #2— Sample Response
{
"contentInfos": [
{
"streamId": 76030,
"fileSize": 2,
"encodedInfo": "76033%3A2%3A150329%3A76033"
},
{
"streamId": 76031,
"fileSize": 2,
"encodedInfo": "76035%3A2%3A150329%3A76035"
},
{
"streamId": 76032,
"fileSize": 2,
"encodedInfo": "76034%3A2%3A150329%3A76034"
}
]
}
Stage #3— In the Stage #3 request body, specify the required attributes along with the information obtained from the Stage #2 response for uploading the respective attachment to the specified part. Use the following POST URI with the request body:
URI
POST /Windchill/servlet/odata/ProdMgmt/Parts(‘OR:wt.part.WTPart:280560’)/PTC.ProdMgmt.UploadStage3Action
Request Headers
Content-Type: application/json
CSRF_NONCE: <Use the value from Fetch NONCE example>
Request body
{
"ContentInfo": [
{
"StreamId": 76030,
"EncodedInfo": "76033%3A2%3A150329%3A76033",
"FileName": "DesignSpec.pdf",
"PrimaryContent": true,
"MimeType": "application/pdf",
"FileSize": 2
},
{
"StreamId": 76031,
"EncodedInfo": "76035%3A2%3A150329%3A76035",
"FileName": "Notebook.xlsx",
"PrimaryContent": false,
"MimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"FileSize": 2
},
{
"StreamId": 76032,
"EncodedInfo": "76034%3A2%3A150329%3A76034",
"FileName": "RenderedImage.png",
"PrimaryContent": false,
"MimeType": "image/png",
"FileSize": 2
}
]
}
To update an attached file (for example, to attach a file of the later version), use the PUT method.
Example: Uploading a URL Content to a Part
To upload a URL content to the specified part, use the following POST URI with the request body:
URI
POST /Windchill/servlet/odata/ProdMgmt/Parts('OR:wt.part.WTPart:280560')/Attachments
Request Headers
Content-Type: application/json
CSRF_NONCE: <Use the value from Fetch NONCE example>
Request Body
{
"Description": "Google URL",
"DisplayName": "Google attachment",
"UrlLocation": "www.google.com",
"Comments": "test url location"
}
To update a URL content or an attribute in the URL content, you must set the Part Management > Attachments on parts preference to Yes in the Preference Management utility in Windchill.
To update existing URL content, use the following PUT URI with the request body:
URI
PUT /Windchill/servlet/odata/ProdMgmt/Parts('OR:wt.part.WTPart:280560')/Attachments('OR:wt.content.URLData:280598')
Request Headers
Content-Type: application/json
CSRF_NONCE: <Use the value from Fetch NONCE example>
Request Body
{
"Description": "Google URL 1",
"DisplayName": "Google attachment1",
"UrlLocation": "https://www.google.com"
}
To update an attribute in the existing URL content, use the following PATCH URI with the request body:
URI
PATCH /Windchill/servlet/odata/ProdMgmt/Parts('OR:wt.part.WTPart:280560')/Attachments('OR:wt.content.URLData:280598')
Request Headers
Content-Type: application/json
CSRF_NONCE: <Use the value from Fetch NONCE example>
Request Body
{
"DisplayName": "Google attachment2"
}
Example: Uploading External Data to a Part
To upload external stored content, use the following POST URI with the request body.
URI
POST /Windchill/servlet/odata/ProdMgmt/Parts('OR:wt.part.WTPart:280560')/Attachments
Request Headers
Content-Type: application/json
CSRF_NONCE: <Use the value from Fetch NONCE example>
Request Body
{
"Description": "Google3 ExternalData",
"DisplayName": "map.jpg",
"ExternalLocation": "http://mserver.ptcnet.ptc.com/photos"
}
* 
DisplayName is the name of the file on the external location.
To update external content or an attribute in the external content, you must set the Part Management > Attachments on parts preference to Yes in the Preference Management utility in Windchill.
To update existing external content, use the following PUT URI with the request body:
URI
PUT /Windchill/servlet/odata//Windchill/servlet/odata/ProdMgmt/Parts('OR:wt.part.WTPart:280560')/Attachments('OR:wt.content.ExternalStoredData:280679')
Request Body
{
"Description": "Google3 ExternalData",
"DisplayName": "map2.jpg",
"ExternalLocation": "http://mserver.ptcnet.ptc.com/ptc"
}
To update an attribute in the existing external content, use the following PATCH URI with the request body:
URI
PATCH /Windchill/servlet/odata/ProdMgmt/Parts('OR:wt.part.WTPart:280560')/Attachments('OR:wt.content.ExternalStoredData:280679')
Request Headers
Content-Type: application/json
CSRF_NONCE: <Use the value from Fetch NONCE example>
Request Body
{
"DisplayName": "Google4 ExternalData"
}