0
我有我试图通过SOAP访问,以创建新项目的SDL WorldServer的实例。如何通过SOAP API燃气附件发送DIME消息?
我想使通过谷歌Apps脚本在web应用程序,用户可以上传文件到,我可以用它来发送和使项目/报价斑点。我能够使SOAP适用于任何不需要附件的命令。但添加附件会使事情复杂化。我试过通过手动生成发送相同的SOAP消息,但是,当我尝试通过手动生成发送相同的SOAP消息时,我已经成功地通过soapui(但是,soapui为我处理DIME格式,因此我假设我需要使用DIME?消息我自己,我得到一个SOAP错误,指出:
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>java.io.IOException: Stream closed.</faultstring>
<detail><ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">SNJWS112</ns1:hostname></detail>
这里是我使用的示例代码:
function makeDimeHeader (position, isChunk, id, contentType, data) {
// ref: http://xml.coverpages.org/draft-nielsen-dime-02.txt
var bin = ""
// version 1
bin += "00001"
if (position == "start") {
bin += "10"
} else if (position == "finish") {
bin += "01"
} else if (position == "middle") {
bin += "00"
} else if (position == "only") {
bin += "11"
} else {
throw "Error: position must be 'start', 'only', 'middle', or 'finish'"
}
if (isChunk) {
bin += "1"
} else {
bin += "0"
}
if (id.constructor !== Array) throw "Error: id must be a byte array"
if (contentType.constructor !== Array) throw "Error: contentType must be a byte array"
if (data.constructor !== Array) throw "Error: data must be a byte array"
var textType = Utilities.newBlob(contentType).getDataAsString()
if (textType.slice(0,4) == "http") {
bin += "0010"
} else if (contentType.length == 0) {
bin += "0000"
} else {
bin += "0001"
}
// RESERVED
bin += "0000"
// OPTIONS LENGTH
bin += "0000000000000000"
bin += ("0000000000000000" + id.length.toString(2)).slice(-16)
bin += ("0000000000000000" + contentType.length.toString(2)).slice(-16)
bin += ("00000000000000000000000000000000" + data.length.toString(2)).slice(-32)
var bytes = []
for (var i = 0; i < bin.length/8; i++) {
num = parseInt(bin.slice(i*8,(i*8)+8),2);
// Byte[] is an Int8Array, not Uint8Array
if (num > 127) num = num - 256
bytes.push(num)
}
// PADDING TO CLOSEST 4 BYTES
if (id.length % 4 != 0) bytes = bytes.concat([0, 0, 0].slice(0, 4 - (id.length % 4)))
bytes = bytes.concat(id)
// PADDING TO CLOSEST 4 BYTES
if (contentType.length % 4 != 0) bytes = bytes.concat([0, 0, 0].slice(0, 4 - (contentType.length % 4)))
bytes = bytes.concat(contentType)
// PADDING TO CLOSEST 4 BYTES
if (data.length % 4 != 0) bytes = bytes.concat([0, 0, 0].slice(0, 4 - (data.length % 4)))
bytes = bytes.concat(data)
return bytes
}
function testPost() {
var file = UrlFetchApp.fetch("https://.../somedoc.xlsx");
var fileBlob = file.getBlob();
var fileBytes = fileBlob.getBytes();
var contentType = 'application/dime; charset=Utf-8';
var data = Utilities.newBlob(
"<?xml version=\"1.0\"?>\r\n" +
"<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:com=\"http://www.idiominc.org/com.idiominc.webservices.WorkflowWSWorkflowManager\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
"<soapenv:Header/>" +
"<soapenv:Body>" +
"<com:createProjectGroup7_ soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
"<token xsi:type=\"xsd:string\">0000000000</token>" +
"<name xsi:type=\"xsd:string\">TEST NEW PROJECT</name>" +
"<locales xsi:type=\"data:stringArray\" soapenc:arrayType=\"xsd:string[]\" xmlns:data=\"http://webservices.idiominc.com/data\">" +
"<item type=\"xsd:string\">English (United States)</item>" +
"<item type=\"xsd:string\">Korean</item>" +
"</locales>" +
"<attachedFile xsi:type=\"data:stringArray\" soapenc:arrayType=\"xsd:string[]\" xmlns:data=\"http://webservices.idiominc.com/data\">" +
"<file type=\"xsd:string\">test.xlsx</file>" +
"</attachedFile>" +
"<client xsi:type=\"xsd:string\">TEST CLIENT</client>" +
"<projectType xsi:type=\"xsd:string\">TEST PROJECT TYPE</projectType>" +
"<customAisProperties xsi:type=\"data:stringArray\" soapenc:arrayType=\"xsd:string[]\" xmlns:data=\"http://webservices.idiominc.com/data\"/>" +
"</com:createProjectGroup7_>" +
"</soapenv:Body>" +
"</soapenv:Envelope>").getBytes()
var soapcontent = Utilities.newBlob(
"http://schemas.xmlsoap.org/soap/envelope/"
).getBytes()
var firstSoapDime = makeDimeHeader("start", false, [], soapcontent, data)
var filecontent = Utilities.newBlob(
"application/octet-stream"
).getBytes()
var lastFileData = makeDimeHeader("finish", false, Utilities.newBlob("test.xlsx").getBytes(), filecontent, fileBytes)
var payloadbytes = firstSoapDime.concat(lastFileData)
var headers =
{
"SOAPAction" : ""
};
var payload = Utilities.newBlob(payloadbytes).getDataAsString();
var options =
{
"method" : "post",
"headers" : headers,
"contentType": contentType,
"contentLength": payloadbytes.length,
"payload" : payload,
"muteHttpExceptions" : true
};
var response = UrlFetchApp.fetch("https://<ourdomain>.sdlproducts.com/ws/services/WorkflowWSWorkflowManager", options);
Logger.log(payload)
Logger.log(response)
};
如果任何人都可以看看我的代码,并发现任何问题,或提出任何其他替代品,我将不胜感激。谢谢。
编辑:我发现在我的原代码中的问题(一个或多个)。
- DIME消息中的0x00填充会在数据后发生,而不是之前。
- 而不是字符串,我需要有效载荷附加作为字节[]数组。然而,这不能成为一个其中I Concat的2个或更多字节[]数组,因为我认为它们被作为一个正常的阵列处理。所以我通过Utilities.newBlob()。getBytes()来创建一个新的Byte []数组,以防万一。这是通过它的最后一部分。
正确的代码如下。
function makeDimeHeader (position, isChunk, id, contentType, data) {
// ref: http://xml.coverpages.org/draft-nielsen-dime-02.txt
var bin = ""
// version 1
bin += "00001"
if (position == "start") {
bin += "10"
} else if (position == "finish") {
bin += "01"
} else if (position == "middle") {
bin += "00"
} else if (position == "only") {
bin += "11"
} else {
throw "Error: position must be 'start', 'only', 'middle', or 'finish'"
}
if (isChunk) {
bin += "1"
} else {
bin += "0"
}
if (id.constructor !== Array) throw "Error: id must be a byte array"
if (contentType.constructor !== Array) throw "Error: contentType must be a byte array"
if (data.constructor !== Array) throw "Error: data must be a byte array"
var textType = Utilities.newBlob(contentType).getDataAsString()
if (textType.slice(0,4) == "http") {
bin += "0010"
} else if (contentType.length == 0) {
bin += "0000"
} else {
bin += "0001"
}
// RESERVED
bin += "0000"
// OPTIONS LENGTH
bin += "0000000000000000"
bin += ("0000000000000000" + id.length.toString(2)).slice(-16)
bin += ("0000000000000000" + contentType.length.toString(2)).slice(-16)
bin += ("00000000000000000000000000000000" + data.length.toString(2)).slice(-32)
var bytes = []
for (var i = 0; i < bin.length/8; i++) {
num = parseInt(bin.slice(i*8,(i*8)+8),2);
// Byte[] is an Int8Array, not Uint8Array
if (num > 127) num = num - 256
bytes.push(num)
}
bytes = bytes.concat(id)
// PADDING TO CLOSEST 4 BYTES
if (id.length % 4 != 0) bytes = bytes.concat([0, 0, 0].slice(0, 4 - (id.length % 4)))
bytes = bytes.concat(contentType)
// PADDING TO CLOSEST 4 BYTES
if (contentType.length % 4 != 0) bytes = bytes.concat([0, 0, 0].slice(0, 4 - (contentType.length % 4)))
bytes = bytes.concat(data)
// PADDING TO CLOSEST 4 BYTES
if (data.length % 4 != 0) bytes = bytes.concat([0, 0, 0].slice(0, 4 - (data.length % 4)))
return bytes
}
function testPost() {
var file = UrlFetchApp.fetch("https://.../somedoc.xlsx");
var fileBlob = file.getBlob();
var fileBytes = fileBlob.getBytes();
var contentType = 'application/dime';
var data = Utilities.newBlob(
"<?xml version=\"1.0\"?>\r\n" +
"<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:com=\"http://www.idiominc.org/com.idiominc.webservices.WorkflowWSWorkflowManager\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
"<soapenv:Header/>" +
"<soapenv:Body>" +
"<com:createProjectGroup7_ soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
"<token xsi:type=\"xsd:string\">0000000000</token>" +
"<name xsi:type=\"xsd:string\">TEST NEW PROJECT</name>" +
"<locales xsi:type=\"data:stringArray\" soapenc:arrayType=\"xsd:string[]\" xmlns:data=\"http://webservices.idiominc.com/data\">" +
"<item type=\"xsd:string\">English (United States)</item>" +
"<item type=\"xsd:string\">Korean</item>" +
"</locales>" +
"<attachedFile xsi:type=\"data:stringArray\" soapenc:arrayType=\"xsd:string[]\" xmlns:data=\"http://webservices.idiominc.com/data\">" +
"<file type=\"xsd:string\">test.xlsx</file>" +
"</attachedFile>" +
"<client xsi:type=\"xsd:string\">TEST CLIENT</client>" +
"<projectType xsi:type=\"xsd:string\">TEST PROJECT TYPE</projectType>" +
"<customAisProperties xsi:type=\"data:stringArray\" soapenc:arrayType=\"xsd:string[]\" xmlns:data=\"http://webservices.idiominc.com/data\"/>" +
"</com:createProjectGroup7_>" +
"</soapenv:Body>" +
"</soapenv:Envelope>").getBytes()
var soapcontent = Utilities.newBlob(
"http://schemas.xmlsoap.org/soap/envelope/"
).getBytes()
var firstSoapDime = makeDimeHeader("start", false, [], soapcontent, data)
var filecontent = Utilities.newBlob(
"application/octet-stream"
).getBytes()
var lastFileData = makeDimeHeader("finish", false, Utilities.newBlob("test.xlsx").getBytes(), filecontent, fileBytes)
var payloadbytes = firstSoapDime.concat(lastFileData)
var headers =
{
"SOAPAction" : ""
};
var payload = Utilities.newBlob(payloadbytes).getBytes();
var options =
{
"method" : "post",
"headers" : headers,
"contentType": contentType,
"contentLength": payloadbytes.length,
"payload" : payload,
"muteHttpExceptions" : true
};
var response = UrlFetchApp.fetch("https://<ourdomain>.sdlproducts.com/ws/services/WorkflowWSWorkflowManager", options);
Logger.log(payload)
Logger.log(response)
};