locked
Need to capture PDF stream returned from WSDL web service call RRS feed

  • Question

  • User-1106658503 posted

    Hi all,

    I need to capture the PDF stream from a call to a web service method.  I do not know the specifics of the method but I know it's return type is void.  I assume it returns the PDF through the Response.OutputStream.Write().  Since it has no return value per say, how would I do that?

    The call to the web service method looks something like that:

    MYServiceReference.ServiceCIESoapClient ref = new MYServiceReference.ServiceCIESoapClient();
    ref.GetPdf(auth_string, filename);

    I loooked into using HttpWebRequest, HttpWebResponse, async Task, etc, but I miss experience to put it all together.

    Any suggestions?

    Sunday, December 1, 2013 8:49 PM

Answers

  • User-417640953 posted

    The obvious question is how can I read back the ResponseStream the right way so that the file I generate has the right size?  Also, this is a test method but I need to pass parameters (filename, auth string) to my web service call.  How would I do that?

    Hi miro_rc,

    Thanks for your response.

     byte[] buffer = new byte[102400];

    The buffer defined in code behind to accept the response stream from the web service. It is right if its' size more than the size of response stream.

    From your description, the web service use the "Response.OutputStream.Write" to output pdf file. And it can work partly. Just Like below.

      while (dataLengthToRead > 0 && HttpContext.Current.Response.IsClientConnected)
                    {
                        int lengthRead = iStream.Read(buffer, 0, Convert.ToInt32(ChunkSize));
                        HttpContext.Current.Response.OutputStream.Write(buffer, 0, lengthRead);
                        HttpContext.Current.Response.Flush();
                        dataLengthToRead = dataLengthToRead - lengthRead;
                    }

    If you want to pass the parameters to the web service and the request is "Get". Just add the parameters to the url.

      string url = "http://localhost:32259/12-month/12-3/MyWebservice.asmx/DownloadFileByPartly?filename=abc.pdf&auth=jhon";

    If you want to pass parameters using the "Post", please check below fragment code.

      string responseBody = string.Empty;
      string requestBody = "[{\"filename\":\"abc.pdf\",\"auth\":\"jhon\"}]";
      byte[] byteData = UTF8Encoding.UTF8.GetBytes(requestBody.ToString());
      request.Method = "POST";
      request.ContentLength = byteData.Length;
      // Write data 
      using (Stream postStream = request.GetRequestStream())
         {
                          postStream.Write(byteData, 0, byteData.Length);
         } 


    Thanks.

    Best Regards!

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, December 5, 2013 9:47 PM

All replies

  • User-417640953 posted

    miro_rc

     I assume it returns the PDF through the Response.OutputStream.Write().  Since it has no return value per say, how would I do that?

    Hi miro_rc,

    Thanks for your post.

    According to your description, I see the web method of the service has no return type. And it should like below.

    [WebMethod]
            public void DownloadFileByPartly() {
                string filePath = Server.MapPath("~/12-month/12-3/TestPage.pdf");//path
    
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
    
                if (fileInfo.Exists == true)
                {
                   const long ChunkSize = 102400;//100k
                     byte[] buffer = new byte[ChunkSize];
    
                    HttpContext.Current.Response.Clear();
                    System.IO.FileStream iStream = System.IO.File.OpenRead(filePath);
                    long dataLengthToRead = iStream.Length;
                   
                    while (dataLengthToRead > 0 && HttpContext.Current.Response.IsClientConnected)
                    {
                        int lengthRead = iStream.Read(buffer, 0, Convert.ToInt32(ChunkSize));
                          HttpContext.Current.Response.OutputStream.Write(buffer, 0, lengthRead);
                        HttpContext.Current.Response.Flush();
                        dataLengthToRead = dataLengthToRead - lengthRead;
                    }
                   // HttpContext.Current.Response.Close();
                }
            
            }

    Then you can call the web service using HttpWebRequest like below.

     //the url of the web service
                string url = "http://localhost:32259/12-month/12-3/MyWebservice.asmx/DownloadFileByPartly";
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
                request.Headers.Clear(); 
                request.Method = "Get"; 
                Encoding encode = Encoding.GetEncoding("utf-8");
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();  
                //get the response file stream
                Stream reader = response.GetResponseStream();
                byte[] buffer = new byte[102400];
                int length = reader.Read(buffer, 0, Convert.ToInt32(102400));
                Response.ContentType = "application/octet-stream";
                Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode("myfile.pdf"));
                //output to client
                Response.BinaryWrite(buffer);

    HttpWebRequest supports async, for how to do it, please check below link.

    http://stackoverflow.com/questions/8519064/how-consume-a-web-service-asynchronous

    http://msdn.microsoft.com/en-us/library/86wf6409(v=vs.110).aspx

     

    Thanks.

    Best Regards!

    Wednesday, December 4, 2013 1:51 AM
  • User-1106658503 posted

    Hi Fuxiang, thank you very much for your help.

    Your reply helped me figure some things out but your solution yields a pdf file with the wrong size.  In fact it has the size of the buffer.

    I found this example which looks right to me but I still end up with a pdf file with the wrong size.  So the file won't open because it is corrupted.

                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://localhost:3533/MyService.asmx?op=GetPdf");
                //webRequest.ContentType = "text/xml;charset=\"utf-8\"";
                webRequest.ContentType = "application/pdf";
                webRequest.Method = "GET";
    
                int bufferSize = 4096;
                var buffer = new byte[bufferSize];
                using (var httpResponse = (HttpWebResponse)webRequest.GetResponse())
                {
                    using (var ms = new System.IO.MemoryStream())
                    {
                        using (var reader = new System.IO.BinaryReader(httpResponse.GetResponseStream()))
                        {
                            int bytesRead;
                            while ((bytesRead = reader.Read(buffer, 0, bufferSize)) > 0)
                            {
                                ms.Write(buffer, 0, bytesRead);
                            }
                        }
    
                        HttpContext.Current.Response.Clear();
                        HttpContext.Current.Response.ClearHeaders();
                        // get the data of the stream
                        ms.Position = 0;
                        byte[] uploadData = ms.ToArray();
                        HttpContext.Current.Response.ContentType = "application/pdf";
                        HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode("filename.pdf"));
                        HttpContext.Current.Response.OutputStream.Write(uploadData, 0, uploadData.Length);
                        HttpContext.Current.Response.Flush();
                        HttpContext.Current.Response.End();
                    }
                }


    The obvious question is how can I read back the ResponseStream the right way so that the file I generate has the right size?  Also, this is a test method but I need to pass parameters (filename, auth string) to my web service call.  How would I do that?

    Thursday, December 5, 2013 10:31 AM
  • User-417640953 posted

    The obvious question is how can I read back the ResponseStream the right way so that the file I generate has the right size?  Also, this is a test method but I need to pass parameters (filename, auth string) to my web service call.  How would I do that?

    Hi miro_rc,

    Thanks for your response.

     byte[] buffer = new byte[102400];

    The buffer defined in code behind to accept the response stream from the web service. It is right if its' size more than the size of response stream.

    From your description, the web service use the "Response.OutputStream.Write" to output pdf file. And it can work partly. Just Like below.

      while (dataLengthToRead > 0 && HttpContext.Current.Response.IsClientConnected)
                    {
                        int lengthRead = iStream.Read(buffer, 0, Convert.ToInt32(ChunkSize));
                        HttpContext.Current.Response.OutputStream.Write(buffer, 0, lengthRead);
                        HttpContext.Current.Response.Flush();
                        dataLengthToRead = dataLengthToRead - lengthRead;
                    }

    If you want to pass the parameters to the web service and the request is "Get". Just add the parameters to the url.

      string url = "http://localhost:32259/12-month/12-3/MyWebservice.asmx/DownloadFileByPartly?filename=abc.pdf&auth=jhon";

    If you want to pass parameters using the "Post", please check below fragment code.

      string responseBody = string.Empty;
      string requestBody = "[{\"filename\":\"abc.pdf\",\"auth\":\"jhon\"}]";
      byte[] byteData = UTF8Encoding.UTF8.GetBytes(requestBody.ToString());
      request.Method = "POST";
      request.ContentLength = byteData.Length;
      // Write data 
      using (Stream postStream = request.GetRequestStream())
         {
                          postStream.Write(byteData, 0, byteData.Length);
         } 


    Thanks.

    Best Regards!

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, December 5, 2013 9:47 PM
  • User-1106658503 posted

    Thanks for your help Fuxiang, very helpful.

    Tuesday, December 10, 2013 2:31 PM