cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - You can change your system assigned username to something more personal in your community settings. X

Error java.io.StreamCorruptedException: invalid stream header: 2D2D2D2D when uploading a WTDocument

smartel
12-Amethyst

Error java.io.StreamCorruptedException: invalid stream header: 2D2D2D2D when uploading a WTDocument

@VanVelZ In reference of your topic.

 

Hello, Would you agree to share the whole code of your final solution.

I'm struggling with something similar, I need to POST an upload of a WTDocument and I'm receiving an error: java.io.StreamCorruptedException: invalid stream header: 2D2D2D2D. I'm trying to do it using Java class combine with REST. 

Here is the  prototype method I'm testing:


public static void uploadOData2(String serviceUrl, String payload, String username, String password, String certPath, String methode, String csrfNonce) {
HttpsURLConnection httpsConn = null;
OutputStream outputStream = null;
try {
// Load the server certificate
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new FileInputStream(certPath);
X509Certificate ca = (X509Certificate) cf.generateCertificate(caInput);
caInput.close();

// Create a KeyStore containing the trusted certificate
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the certificate in the KeyStore
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);

// Create an SSLContext that uses the TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
File file = new File("c:/temp/test.txt");

if (file.exists()) {
// Set the default SSLContext
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

URL url = new URL(serviceUrl);
httpsConn = (HttpsURLConnection) url.openConnection();
httpsConn.setRequestMethod(methode.toUpperCase());
httpsConn.setRequestProperty("Content-Type", "text/plain");
httpsConn.setRequestProperty("Accept", "text/plain");
httpsConn.setRequestProperty("Content-Disposition", "form-data; name=\"file\"; filename=\"test.txt\"");
httpsConn.setRequestProperty("Content-Length", String.valueOf(file.length()));
httpsConn.setDoOutput(true);
httpsConn.setRequestProperty("CSRF_NONCE", csrfNonce);
DataOutputStream wr = new DataOutputStream(httpsConn.getOutputStream());
FileInputStream fileInputStream = new FileInputStream(file);
byte[] fileContent = fileInputStream.readAllBytes();
fileInputStream.close();
// Append binary content to payload
String boundary = "\r\n---------------------------boundary\r\n";
payload += "\r\n";
payload += fileContent;
payload += boundary;
// Send payload
wr.write(payload.getBytes());
wr.flush();
wr.close();
httpsConn.connect();

int responseCode = httpsConn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
// OData POST request successful
} else {
// OData POST request failed. Server returned response code
InputStream errorStream = httpsConn.getErrorStream();
if (errorStream != null) {
byte[] errorBytes = errorStream.readAllBytes();
// Error response
}
}

httpsConn.disconnect();
} else {
// File not found
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null) outputStream.close();
if (httpsConn != null) httpsConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}

 

ACCEPTED SOLUTION

Accepted Solutions

Probably my question unclear.

The used case we have, is a file is generated by a test bench, we want the operator to upload the file into Windchill.

So we created an interface, when he user click it request his username and password then send the file into Windchill and attach it to a wtpart. We wanted to do it using REST api through a java class. 

Note that an empty wtdocument is already created before through a Workflow process.

So I refer to Article - CS305415 - How to update the Primary content of an existing WTDocuments via External Storage method using OData REST Services in Windchill PDMLink

So, here is my solution for this problem in case it can help someone else:

/**
 * Executes a PUT request to the specified OData service URL to upload a file.
 * @param serviceUrl the OData service URL ex.: serverUrl + "/servlet/odata/DocMgmt/Documents('OR:wt.doc.WTDocument:" + idA2A2 + "')/PrimaryContent";
 * @param username   the username for basic authentication
 * @param password   the password for basic authentication
 * @param certPath   the path to the SSL certificate
 * @param csrfNonce  the CSRF nonce token
 * @param filePath   the path to the file to be uploaded ex.: "C:\TEMP\Test123.xls"
 * @return the response from the OData service
 */
public static String putOData(String serviceUrl, String username, String password, String certPath, String csrfNonce, String filePath) {
HttpsURLConnection httpsConn = null;
OutputStream outputStream = null;
String response = "";
try {
//Method to get the SSL context
SSLContext sslContext = getSSLContext(certPath);
File file = new File(filePath);
 
// Set the default SSLContext
HttpClient httpClient = HttpClientBuilder.create().setSSLContext(sslContext).build();
HttpPut request = new HttpPut(serviceUrl);
 
if (file != null && file.exists()) {
// Add Basic Authentication header
String auth = username + ":" + password;
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
request.addHeader("CSRF_NONCE", csrfNonce);
request.addHeader("Accept", "application/json");
request.addHeader("Authorization", "Basic " + encodedAuth);
 
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("File", file, ContentType.DEFAULT_BINARY, file.getName());
builder.addTextBody("key", file.getName(), ContentType.TEXT_PLAIN);
 
HttpEntity entity = builder.build();
request.setEntity(entity);
 
log.info("FileSize: {}" + (file.length() / 1024.0));
HttpResponse httpResponse = httpClient.execute(request);
response = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} else {
// File not found
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null)
outputStream.close();
if (httpsConn != null)
httpsConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}

 

 

View solution in original post

4 REPLIES 4
HelesicPetr
22-Sapphire I
(To:smartel)

Hi @smartel 

This is not case by Windchill or any windchill api methods.

It is general mistake

Check google how to solve the invalid stream header exception

invalid stream header

java.io.StreamCorruptedException: invalid stream header

 

PetrH

Probably my question unclear.

The used case we have, is a file is generated by a test bench, we want the operator to upload the file into Windchill.

So we created an interface, when he user click it request his username and password then send the file into Windchill and attach it to a wtpart. We wanted to do it using REST api through a java class. 

Note that an empty wtdocument is already created before through a Workflow process.

So I refer to Article - CS305415 - How to update the Primary content of an existing WTDocuments via External Storage method using OData REST Services in Windchill PDMLink

So, here is my solution for this problem in case it can help someone else:

/**
 * Executes a PUT request to the specified OData service URL to upload a file.
 * @param serviceUrl the OData service URL ex.: serverUrl + "/servlet/odata/DocMgmt/Documents('OR:wt.doc.WTDocument:" + idA2A2 + "')/PrimaryContent";
 * @param username   the username for basic authentication
 * @param password   the password for basic authentication
 * @param certPath   the path to the SSL certificate
 * @param csrfNonce  the CSRF nonce token
 * @param filePath   the path to the file to be uploaded ex.: "C:\TEMP\Test123.xls"
 * @return the response from the OData service
 */
public static String putOData(String serviceUrl, String username, String password, String certPath, String csrfNonce, String filePath) {
HttpsURLConnection httpsConn = null;
OutputStream outputStream = null;
String response = "";
try {
//Method to get the SSL context
SSLContext sslContext = getSSLContext(certPath);
File file = new File(filePath);
 
// Set the default SSLContext
HttpClient httpClient = HttpClientBuilder.create().setSSLContext(sslContext).build();
HttpPut request = new HttpPut(serviceUrl);
 
if (file != null && file.exists()) {
// Add Basic Authentication header
String auth = username + ":" + password;
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
request.addHeader("CSRF_NONCE", csrfNonce);
request.addHeader("Accept", "application/json");
request.addHeader("Authorization", "Basic " + encodedAuth);
 
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("File", file, ContentType.DEFAULT_BINARY, file.getName());
builder.addTextBody("key", file.getName(), ContentType.TEXT_PLAIN);
 
HttpEntity entity = builder.build();
request.setEntity(entity);
 
log.info("FileSize: {}" + (file.length() / 1024.0));
HttpResponse httpResponse = httpClient.execute(request);
response = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} else {
// File not found
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null)
outputStream.close();
if (httpsConn != null)
httpsConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}

 

 

HelesicPetr
22-Sapphire I
(To:smartel)

Hi @smartel 

I am just curious. Where was the issue with the invalid stream header ?

Thank you for your answer.

PetrH

Hi @HelesicPetr 

Honestly, using the PUT method as described in CS305415 is a workaround.
With my previous code, I attempted to use the REST UploadStage 1, 2, and 3 actions.

I successfully completed stages 1 and 2, and the file was uploaded to Windchill's default upload vault.

However, I was never able to execute UploadStage3Action due to a persistent header error.

 

So as 2nd trial. I decided to try to load it using ApplicationData.newApplicationData and update the WTDoc primary. This was working since the file was uploaded.

But this was creating a new file in the vault.

And then when I ran removed unref the 1st uploaded file was not removed. 

So I had to manually delete it.

 

So I end up with CS305415. which was simpler.

If you have any ideas or an example, it could be great for knowledge.


Thanks for asking,

Steve

Announcements


Top Tags