Community Tip - Visit the PTCooler (the community lounge) to get to know your fellow community members and check out some of Dale's Friday Humor posts! X

REST API POST method to Upload Primary Content to Document

MT_11904685
8-Gravel

REST API POST method to Upload Primary Content to Document

I am trying to upload the primary content to a document using REST API. I found information on knowledge hub to do it using Upload Stage 1, Upload Stage 2, Upload Stage 3 actions. I am facing issue while stage 2 action as it is not available in windchill rest services(screenshot attached). I am wondering if it is possible to customize the Document Management domain to perform POST action to upload document primary content directly through rest api. Any hint or assistance will be greatly appreciated.

Thanks in advance for time and consideration.

 

Screenshot 2024-11-25 114407.png

 

ACCEPTED SOLUTION

Accepted Solutions
tm-4
12-Amethyst
(To:MT_11904685)

Hi,

The batch request which i posted, will create a document with "helloworld.txt" text file as primary content. No further actions needed . If there is other file type needed to be added as primary content, then you need to write some code to serialize the file. Below is the code snippet with okhttp client . The code will create a document in windchill with a excel file as primary content.

okhttp3.MultipartBody.Builder batchBuilder =
                new okhttp3.MultipartBody.Builder("batch").setType(okhttp3.MultipartBody.MIXED);

        // Changeset part
        okhttp3.MultipartBody.Builder changesetBuilder =
                new okhttp3.MultipartBody.Builder("changeset").setType(okhttp3.MultipartBody.MIXED);

        // Changeset part
        okhttp3.MultipartBody.Builder contenttBuilder =
                new okhttp3.MultipartBody.Builder("ContentSeparator").setType(okhttp3.MultipartBody.FORM);

        // First part of changeset
        changesetBuilder.addPart(
                Headers.of(
                        "Content-ID", "1",
                        "Content-Transfer-Encoding", "binary"),
                RequestBody.create(
                        "POST Documents HTTP/1.1\n"
                                + "Content-Type: application/json\n\n"
                                + "{\n"
                                + "  \"Name\": \"Created Through PostMan\",\n"
                                + "  \"@odata.type\": \"PTC.DocMgmt.MyDocSubtype\",\n"
                                + "  \"Context@odata.bind\": \"Containers('OR:wt.pdmlink.PDMLinkProduct:XXXXXX')\",\n"
                                + "  \"Folder@odata.bind\": \"Folders('OR:wt.folder.SubFolder:XXXXXX')\",\n"
                                + "  \"Attr1\": {\n"
                                + "        \"Value\": \"EN\"\n"
                                + "      },\n"
                                + "       \"Attr2\": {\n"
                                + "        \"Value\": \"1\"\n"
                                + "      },\n"
                                + "      \"Attr3\": \"10\"\n"
                                + "}\n",
                        MediaType.parse("application/http")));

        // Second part of changeset
        changesetBuilder.addPart(
                Headers.of(
                        "Content-ID", "2",
                        "Content-Transfer-Encoding", "binary"),
                RequestBody.create(
                        "POST $1/PTC.DocMgmt.CheckOut HTTP/1.1\n"
                                + "Content-Type: application/json\n\n"
                                + "{\n"
                                + "\n"
                                + "}\n"
                                + "\n",
                        MediaType.parse("application/http")));

        MediaType MEDIA_TYPE_EXCEL =
                MediaType.parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

        URI propertyURI =
                GenericTest.class
                        .getClassLoader()
                        .getResource("PartLoaderTemplate_LoadTesting.xlsx")
                        .toURI();
        String excelpath = Paths.get(propertyURI).toString();
        File excelFile = new File(excelpath);

        contenttBuilder.addFormDataPart(
                "primaryFilepathInput",
                excelFile.getName(),
                RequestBody.create(MEDIA_TYPE_EXCEL, excelFile));

        Buffer rb = new Buffer();
        ((RequestBody) contenttBuilder.build()).writeTo(rb);

        changesetBuilder.addPart(
                Headers.of(
                        "Content-ID", "3",
                        "Content-Transfer-Encoding", "binary"),
                RequestBody.create(
                        "PUT $2/PrimaryContent HTTP/1.1\n"
                                + "Content-Type: multipart/form-data; boundary=ContentSeparator\n\n"
                                + rb.readUtf8(),
                        MediaType.parse("application/http")));

        // Fourth part of changeset
        changesetBuilder.addPart(
                Headers.of(
                        "Content-ID", "4",
                        "Content-Transfer-Encoding", "binary"),
                RequestBody.create(
                        "POST $2/PTC.DocMgmt.CheckIn HTTP/1.1\n"
                                + "Content-Type: application/json\n\n"
                                + "{\n"
                                + "\n"
                                + "}\n"
                                + "\n",
                        MediaType.parse("application/http")));

        // Add changeset to batch
        batchBuilder.addPart(changesetBuilder.build());
        Request request =
                new Request.Builder()
                        .url("https://XXXXXXX/Windchill/servlet/odata/v5/DocMgmt/$batch")
                        .post(batchBuilder.build())
                        .header("CSRF_NONCE", "XXXXXXXXXX")
                        .addHeader("Content-Type", "multipart/mixed;boundary=batch")
                        .addHeader("accept", "application/json;odata.metadata=none")
                        .addHeader(
                                "Authorization",
                                "Basic "
                                        + Base64.getEncoder()
                                        .encodeToString(
                                                ("USERNAME" + ":" + "PASSWORD").getBytes(StandardCharsets.UTF_8)))
                        .build();

        try (Response response = client.newCall(request).execute()) {
            // Buffer b = new Buffer();
            // response.request().body().writeTo(b);
            // System.out.println("Req Body: " + b.readUtf8());

            assertAll(() -> assertTrue(response.isSuccessful()), () -> assertNotNull(response.body()));
            String responseBody = response.body().string();
            LOGGER.trace("responseBody = {}", responseBody);

            Pattern pattern = Pattern.compile("boundary=(.+)");
            Matcher matcher = pattern.matcher(responseBody);
            String boundry = "";
            while (matcher.find()) {
                boundry = matcher.group(1);
            }
            LOGGER.trace("boundry = {}", boundry);
        }

 

View solution in original post

4 REPLIES 4

Hi @MT_11904685 

 

Thank you for your question! 

 

Please consider adding screenshot(s) to better understand what you are trying to do in your process. 

 

Please refer to this guideline to make your questions more likely to receive a quick and useful answer. 

This will increase your chances to receive meaningful help from other Community members. 

 

Thank you for your participation and please let me know if you need further assistance! 

 

Best regards,

Catalina
PTC Community Moderator
tm-4
12-Amethyst
(To:MT_11904685)

Hi,

To create a document with content, i suggest to use a batch mode. Refer example below,

 

tm4_0-1732696335818.png

Body

--batch
Content-Type: multipart/mixed;boundary=changeset

--changeset
Content-ID: 1
Content-Type: application/http
Content-Transfer-Encoding:binary

POST Documents HTTP/1.1
Content-Type: application/json

{
  "Name": "Created Through PostMan",
  "@odata.type": "PTC.DocMgmt.MyDocType",
  "Context@odata.bind": "Containers('OR:wt.pdmlink.PDMLinkProduct:xxxxxxx')",
  "Folder@odata.bind": "Folders('OR:wt.folder.SubFolder:xxxxxxxx')",
  "DocumentLanguage": {
        "Value": "EN"
      },
       "ClassificationLevel": {
        "Value": "1"
      },
      "SubType": "10"
}

--changeset
Content-Type: application/http
Content-ID: 2
Content-Transfer-Encoding:binary

POST $1/PTC.DocMgmt.CheckOut HTTP/1.1
Content-Type: application/json

{

}

--changeset
Content-Type: application/http
Content-ID: 3
Content-Transfer-Encoding:binary

PUT $2/PrimaryContent HTTP/1.1
Content-Type: multipart/form-data; boundary=ContentSeparator

--ContentSeparator
Content-Disposition: form-data; name="primaryFilepathInput";filename="helloworld.txt"
Content-Type: text/plain

Hello, World!

--ContentSeparator--

--changeset
Content-Type: application/http
Content-ID: 4
Content-Transfer-Encoding:binary

POST $2/PTC.DocMgmt.CheckIn HTTP/1.1
Content-Type: application/json

{

}

--changeset--

--batch--

 

Thank you for the response. if i understand it right, the document  will be created in the batch request or i have to create it in separate post request. Also I have uploaded the text file using Stage-1, 2, 3 Action available in Windchill rest services module. The problem I am facing now is when I change the data file from simple text file then this method does not work. I would really appreciate your help. thank you.

POST Documents HTTP/1.1
Content-Type: application/json

{
  "Name": "Created Through PostMan",
  "@odata.type": "PTC.DocMgmt.MyDocType",
  "Context@odata.bind": "Containers('OR:wt.pdmlink.PDMLinkProduct:xxxxxxx')",
  "Folder@odata.bind": "Folders('OR:wt.folder.SubFolder:xxxxxxxx')",
  "DocumentLanguage": {
        "Value": "EN"
      },
       "ClassificationLevel": {
        "Value": "1"
      },
      "SubType": "10"
}
tm-4
12-Amethyst
(To:MT_11904685)

Hi,

The batch request which i posted, will create a document with "helloworld.txt" text file as primary content. No further actions needed . If there is other file type needed to be added as primary content, then you need to write some code to serialize the file. Below is the code snippet with okhttp client . The code will create a document in windchill with a excel file as primary content.

okhttp3.MultipartBody.Builder batchBuilder =
                new okhttp3.MultipartBody.Builder("batch").setType(okhttp3.MultipartBody.MIXED);

        // Changeset part
        okhttp3.MultipartBody.Builder changesetBuilder =
                new okhttp3.MultipartBody.Builder("changeset").setType(okhttp3.MultipartBody.MIXED);

        // Changeset part
        okhttp3.MultipartBody.Builder contenttBuilder =
                new okhttp3.MultipartBody.Builder("ContentSeparator").setType(okhttp3.MultipartBody.FORM);

        // First part of changeset
        changesetBuilder.addPart(
                Headers.of(
                        "Content-ID", "1",
                        "Content-Transfer-Encoding", "binary"),
                RequestBody.create(
                        "POST Documents HTTP/1.1\n"
                                + "Content-Type: application/json\n\n"
                                + "{\n"
                                + "  \"Name\": \"Created Through PostMan\",\n"
                                + "  \"@odata.type\": \"PTC.DocMgmt.MyDocSubtype\",\n"
                                + "  \"Context@odata.bind\": \"Containers('OR:wt.pdmlink.PDMLinkProduct:XXXXXX')\",\n"
                                + "  \"Folder@odata.bind\": \"Folders('OR:wt.folder.SubFolder:XXXXXX')\",\n"
                                + "  \"Attr1\": {\n"
                                + "        \"Value\": \"EN\"\n"
                                + "      },\n"
                                + "       \"Attr2\": {\n"
                                + "        \"Value\": \"1\"\n"
                                + "      },\n"
                                + "      \"Attr3\": \"10\"\n"
                                + "}\n",
                        MediaType.parse("application/http")));

        // Second part of changeset
        changesetBuilder.addPart(
                Headers.of(
                        "Content-ID", "2",
                        "Content-Transfer-Encoding", "binary"),
                RequestBody.create(
                        "POST $1/PTC.DocMgmt.CheckOut HTTP/1.1\n"
                                + "Content-Type: application/json\n\n"
                                + "{\n"
                                + "\n"
                                + "}\n"
                                + "\n",
                        MediaType.parse("application/http")));

        MediaType MEDIA_TYPE_EXCEL =
                MediaType.parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

        URI propertyURI =
                GenericTest.class
                        .getClassLoader()
                        .getResource("PartLoaderTemplate_LoadTesting.xlsx")
                        .toURI();
        String excelpath = Paths.get(propertyURI).toString();
        File excelFile = new File(excelpath);

        contenttBuilder.addFormDataPart(
                "primaryFilepathInput",
                excelFile.getName(),
                RequestBody.create(MEDIA_TYPE_EXCEL, excelFile));

        Buffer rb = new Buffer();
        ((RequestBody) contenttBuilder.build()).writeTo(rb);

        changesetBuilder.addPart(
                Headers.of(
                        "Content-ID", "3",
                        "Content-Transfer-Encoding", "binary"),
                RequestBody.create(
                        "PUT $2/PrimaryContent HTTP/1.1\n"
                                + "Content-Type: multipart/form-data; boundary=ContentSeparator\n\n"
                                + rb.readUtf8(),
                        MediaType.parse("application/http")));

        // Fourth part of changeset
        changesetBuilder.addPart(
                Headers.of(
                        "Content-ID", "4",
                        "Content-Transfer-Encoding", "binary"),
                RequestBody.create(
                        "POST $2/PTC.DocMgmt.CheckIn HTTP/1.1\n"
                                + "Content-Type: application/json\n\n"
                                + "{\n"
                                + "\n"
                                + "}\n"
                                + "\n",
                        MediaType.parse("application/http")));

        // Add changeset to batch
        batchBuilder.addPart(changesetBuilder.build());
        Request request =
                new Request.Builder()
                        .url("https://XXXXXXX/Windchill/servlet/odata/v5/DocMgmt/$batch")
                        .post(batchBuilder.build())
                        .header("CSRF_NONCE", "XXXXXXXXXX")
                        .addHeader("Content-Type", "multipart/mixed;boundary=batch")
                        .addHeader("accept", "application/json;odata.metadata=none")
                        .addHeader(
                                "Authorization",
                                "Basic "
                                        + Base64.getEncoder()
                                        .encodeToString(
                                                ("USERNAME" + ":" + "PASSWORD").getBytes(StandardCharsets.UTF_8)))
                        .build();

        try (Response response = client.newCall(request).execute()) {
            // Buffer b = new Buffer();
            // response.request().body().writeTo(b);
            // System.out.println("Req Body: " + b.readUtf8());

            assertAll(() -> assertTrue(response.isSuccessful()), () -> assertNotNull(response.body()));
            String responseBody = response.body().string();
            LOGGER.trace("responseBody = {}", responseBody);

            Pattern pattern = Pattern.compile("boundary=(.+)");
            Matcher matcher = pattern.matcher(responseBody);
            String boundry = "";
            while (matcher.find()) {
                boundry = matcher.group(1);
            }
            LOGGER.trace("boundry = {}", boundry);
        }

 

Announcements

Top Tags