我有一个 SDL 的 WorldServer 实例,我试图通过 SOAP 访问它以创建新项目。
我正在考虑通过 Google Apps 脚本制作一个网络应用程序,用户可以将文件上传到我可以用来发送和制作项目/报价的 blob 中。对于任何不需要附件的命令,我都能让 SOAP 正常工作。但是添加附件会使事情变得复杂。
我已经通过soapui成功地做到了这一点(但是,soapui为我处理了DIME格式,所以我假设我需要使用DIME?),但是当我尝试通过自己手动生成消息来发送相同的SOAP消息时,我收到一个 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)
};
任何人都可以查看我的代码并发现任何问题,或提出任何其他替代方案吗?