0

I'm currently setting up a nodejs server, but an action on that server is to generate a report with jsreport, save it locally and later send it to another service of ours, this being WCF.

In WCF, receive a Stream and save the file in our default directory.

Testing the request on Insomnia, to send a file, works perfectly. But through Node, using Axios or Request, communication occurs, but the generated file is 1kb.

Here is the excerpt from the NodeJS call.

To make de request, I'm using the module Request, v ^2.88.2. (But I've tried with Axios, also)

const formData2 = { 
                            file: fs.createReadStream(reportFile) //the file path
                        }

                        request.post({
                            url: urlSend,//Url of post
                            headers: {
                                'Content-Type': 'multipart/form-data' 
                            },
                            formData: formData2,
                        }, function(error, response, body) {
                            console.log(response);
                        });

The inside of the .pdf file has something like

----------------------------209853603972788926274398 Content-Disposition: form-data; name="file"; filename="APR-RST-06-REV-00.pdf" Content-Type: application/pdf

%PDF-1.4 %׃כיב 1 0 obj <

My C# code where the file is send to (I've made some changes, to remove other codes):

public string uploadFileReport(string arg1, string arg2, string arg3, string arg4, string arg5, Stream file)
        { 

            try
            {  
                if (string.IsNullOrEmpty(arg1) || string.IsNullOrEmpty(arg2) || string.IsNullOrEmpty(arg3))
                    throw new Exception("Um ou mais parâmetros não foram encontrados");

                string diretorioData = "C:\\DATA\\"; 

                //Nome do arquivo.
                string fileName = (string.IsNullOrEmpty(arg5) ? "relatório.pdf" : arg5); 
                string directoryPath = diretorioData + "CRM\\"; 

                if (!Directory.Exists(directoryPath))
                {
                    Directory.CreateDirectory(directoryPath);
                }


                 int length = 0;
                 using (FileStream writer = new FileStream(directoryPath + "\\"+fileName, FileMode.Create))
                 {
                     int readCount;
                     var buffer = new byte[8192];
                     while ((readCount = file.Read(buffer, 0, buffer.Length)) != 0)
                     {
                         writer.Write(buffer, 0, readCount);
                         length += readCount;
                     }
                 }

                return JsonConvert.SerializeObject(new
                {
                    status = "OK", 
                }, Formatting.Indented);
            }
            catch (Exception exc)
            {
                return JsonConvert.SerializeObject(new
                {
                    status = "NOK",
                    message = exc.Message
                }, Formatting.Indented);
            }

        }

For some reason, this Method needed the UriTemplate, on the Interface File. But, to work, on node, I needed to send this values as url param. Perhaps this is the reason, but as I say, from Insomnia, this method works fine.

  [WebInvoke(Method = "POST",
           BodyStyle = WebMessageBodyStyle.WrappedRequest,
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "/uploadFileReport?arg1={arg1}&arg2={arg2}&arg3={arg3}&arg4={arg4}&arg5={arg5}")]
        [OperationContract]
        string uploadFileReport(string arg1, string arg2, string arg3, string arg4, string arg5, Stream file);
  • The line beginning `---------------------------20985360397278` and ending with `\r\n\r\n` is the separator for the multipart content type. The stuff beginning `%PDF-` is, well, the pdf file. It looks like not all of it gets put into the output stream. Which package is your `request` object from? Can you show us how you made that? Please [edit] your question. – O. Jones Mar 19 '20 at 15:00
  • @O.Jones I've changed the question. Hope this is more complete. – CharlesXavier47 Mar 19 '20 at 16:05

2 Answers2

0

WCF doesn’t support Formdata by default, it can be properly handled with the third-party library,
https://archive.codeplex.com/?p=multipartparser
Besides, With enabling stream in WCF, the signature of a function cannot contain more than one argument.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-enable-streaming
Can you access the service description page properly? I don’t think the service can work normally, although you said you can make it work perfectly.
Please refer to this link for the solution to uploading files.
How to upload image of various type (jpg/png/gif) to the server through Stream using WCF web API
Feel free to let me know if there is anything I can help with.

Abraham Qian
  • 7,117
  • 1
  • 8
  • 22
0

For those who may run into this same problem, here's how I manage it. I've changed my request.post to something like:

 const options2 = {
                                method: "POST",
                                url: urlSend,
                                headers: {
                                    "Authorization": "Bearer " + token, 
                                    "Content-Type": "application/octet-stream", 
                                },
                                encoding: 'binary',
                                multipart: [ 
                                    {  
                                        body: fs.createReadStream(reportFile) 
                                    }
                                ],
                            };  

request(options2, function (err, res, body) {
});

And, on my WCF web.config, I've added a binding so accept larger files:

 <binding name="UploadBinding"
                transferMode="Streamed"
              maxBufferPoolSize="2000000000"
              maxBufferSize="2000000000"
                receiveTimeout="01:00:00"
                sendTimeout="01:00:00"
                maxReceivedMessageSize="2000000000" >

          <readerQuotas maxDepth="2000000000"
               maxStringContentLength="2000000000"
               maxArrayLength="2000000000"
               maxBytesPerRead="2000000000"
               maxNameTableCharCount="2000000000" />
        </binding>

And last, added this binding to the service

      <service name="WCFService.CRMH0001">
        <endpoint behaviorConfiguration="AspNetAjaxBehavior" binding="webHttpBinding" bindingConfiguration="UploadBinding"
         contract="WCFService.ICRMH0001" />
      </service>