2

I'm integrating a service to my app which uses SOAP Api. My app is on Node.js. The documentation of the service says that for uploading a file I should use fileData that is of type Byte[] (the bytes of the file chunk). I tried different approaches but none of them worked. I even tried to use Uint8Array (find here on SO some answers) but it didn't worked out either. Here is how my request look like:

const url = `https://memoq.pangea.global:8080/memoQServices/FileManager/FileManagerService`;

async function addFilesToMemoq() {
    try {
        const fileData = fs.readFileSync('./dist/reqfiles/xtm/dev-req.doc', 'base64');        
        const headers = {
            'Content-Type': 'text/xml;charset=UTF-8',
            'soapAction': 'http://kilgray.com/memoqservices/2007/IFileManagerService/AddNextFileChunk',
        };
        for(let chunk of new Uint8Array(fileData)) {
            const xml = `${xmlHeader}
                    <soapenv:Body>
                    <ns:AddNextFileChunk>
                        <ns:fileIdAndSessionId>d00121ab-78ca-4dcf-80b7-9b3d9e4fb905</ns:fileIdAndSessionId>
                        <ns:fileData>${chunk}</ns:fileData>
                    </ns:AddNextFileChunk>
                    </soapenv:Body>
                </soapenv:Envelope>`        
            const { response } = await soapRequest({url, headers, xml});
            //Result is just for breakpoints if needed to debug
            const result = parser.toJson(response.body, {object: true, sanitize: true, trim: true});
        }
        return await finishMemoqFileMove();
        // return result;
    } catch(err) {
        return parser.toJson(err, {object: true, sanitize: true, trim: true}); 
    }
}

async function finishMemoqFileMove() {
    const xml = `${xmlHeader}
                <soapenv:Body>
                    <ns:EndChunkedFileUpload>
                        <ns:fileIdAndSessionId>d00121ab-78ca-4dcf-80b7-9b3d9e4fb905</ns:fileIdAndSessionId>
                    </ns:EndChunkedFileUpload>
                </soapenv:Body>
                </soapenv:Envelope>`
    const headers = {
        'Content-Type': 'text/xml;charset=UTF-8',
        'soapAction': 'http://kilgray.com/memoqservices/2007/IFileManagerService/EndChunkedFileUpload',
    };
    try {
        const { response } = await soapRequest({url, headers, xml});
        const result = parser.toJson(response.body, {object: true, sanitize: true, trim: true});
        return result;
    } catch(err) {
        return parser.toJson(err, {object: true, sanitize: true, trim: true}); 
    }
}

But this request send to the service an empty file. new Uint8Array(fileData) becomes an array of 0s. If I don't use Uint8Array then I'll get error message: Base64 sequence length(3) not valid. Must be a multiple of 4. If I use base64 option in readFileSync - fileData becomes a big string of characters, if I remove that then fileData becomes an array (Buffer) with numbers as elements. For soap requests I'm using node package easy-soap-request. I'd appreciate if anyone could help with this.

If it helps, here is the docs of the service I'm trying to follow.

  • Try Fiddler or any other sniffer and look at the request and response payload – Krivitskiy Grigoriy Jan 24 '20 at 08:42
  • @KrivitskiyGrigoriy didn't get what you mean. –  Jan 24 '20 at 08:45
  • I mean are you sure that you send `0`s to the service when you using `Byte[]`? And how do you get `Byte[]` data? Can you share code where you read file to `Byte[]`? – Krivitskiy Grigoriy Jan 24 '20 at 08:52
  • @KrivitskiyGrigoriy Yes, I'm sure, because I put a breakpoint and see that all elements of `new Uint8Array(fileData)` is [0, 0, 0, .....]. About reading file to `Byte[]` - that is my question. Am i doing it or not in the presented code? How to do that properly? –  Jan 24 '20 at 08:55
  • ok. Does `fileData` contains any data after `fs.readFileSync`? – Krivitskiy Grigoriy Jan 24 '20 at 08:58
  • @KrivitskiyGrigoriy I'e updated my question and wrote about `fileData`. –  Jan 24 '20 at 09:01
  • So this seems to be the problem. You get `base64 string` and pass it to `Uint8Array`. This wouldn't work. You need to create `new Uint8Array` (don't do it in cycle use new variable) and fill it from string. You can see gow to do it correctly here: https://stackoverflow.com/a/21797381/2010469 – Krivitskiy Grigoriy Jan 24 '20 at 09:17
  • @KrivitskiyGrigoriy it doesn't help. Response error: `"The characters '[obj' at offset 0 are not a valid Base64 sequence."` –  Jan 24 '20 at 11:31

0 Answers0