locked
WCF Stream File and return parameter RRS feed

  • Question

  • User836698845 posted

    Hello, I saw an example to stream a file over a WCF web service for streaming a file.

    My interface is

    [OperationContract]
      void UploadFile(RemoteFileInfo request);
        [MessageContract]
        public class RemoteFileInfo : IDisposable
        {
            [MessageHeader(MustUnderstand = true)]
            public string FileName;
    
            [MessageHeader(MustUnderstand = true)]
            public long Length;
    
            [MessageBodyMember(Order = 1)]
            public System.IO.Stream FileByteStream;
    
            public void Dispose()
            {
                if (FileByteStream != null)
                {
                    FileByteStream.Close();
                    FileByteStream = null;
                }
            }
        }

    This works well, but I can't change the UploadFile to a method thar returns a boolean or a string or an int. I understand (I think) that it's because it's a MessageContract. But If e change to a DataContracct I can't stream the file and get an error:

       [OperationContract]
       string UploadFileComResposta(RemoteFileInfoComResposta request);
    
    
    .....
    
    
    [DataContract]
        public class RemoteFileInfoComResposta : IDisposable
        {
            
            public string fileName;
            
            public long length;
           
            public System.IO.Stream fileByteStream;
    
            public void Dispose()
            {
                if (fileByteStream != null)
                {
                    fileByteStream.Close();
                    fileByteStream = null;
                }
            }
            
            [DataMember]
            public string FileName
            {
                get { return fileName; }
                set { fileName = value; }
            }
            [DataMember]
            public long Length
            {
                get { return length; }
                set { length = value; }
            }
            [DataMember]
            public System.IO.Stream FileByteStream
            {
                get { return fileByteStream; }
                set { fileByteStream = value; }
            }
    
        }

    Error:

    "The InnerException message was 'Type 'System.IO.FileStream' with data contract name 'FileStream:http://schemas.datacontract.org/2004/07/System.IO' is not expected."

    The solution must be an easy one, but I'm not getting it. Any help please?

    Thursday, September 26, 2013 5:22 AM

Answers

  • User836698845 posted

    Solution found.

    New DataContract, with a byte array and not a stream to send the file.

    Then for the 64Kb limitation of data,  in the cliente I send maximum 64Kb each time and when have the total byte array, save the file.

    Tested and working

    Forget to add the code.

     [OperationContract]
            string UploadFileDataTTT(FileData fileData);
     
     [DataContract]
        public class FileData
        {
            [DataMember]
            public string FileName
            {
                get;
                set;
            }
             [DataMember]
            public byte[] BufferData
            {
                get;
                set;
            }
            [DataMember]
            public int FilePosition
            {
                get;
                set;
            }
    
    
        }
    
     public string UploadFileDataTTT(FileData fileData)
            {
                try
                {
                    string directoriaUpload = @"C:\upload\";
                    string FilePath = Path.Combine(directoriaUpload, fileData.FileName);
    
                    if (fileData.FilePosition == 0)
                        File.Create(FilePath).Close();
    
                    long tamanho;
                    using (FileStream fileStream = new FileStream(FilePath, FileMode.Open,
                                         FileAccess.ReadWrite, FileShare.Read))
                    {
    
                        fileStream.Seek(fileData.FilePosition, SeekOrigin.Begin);
                        fileStream.Write(fileData.BufferData, 0, fileData.BufferData.Length);
    
                        tamanho = fileStream.Length;
                    }
                    return "Ficheiro Recebido: " + fileData.FileName + "! Tamanho: " + Math.Round ( ConvertBytesToMegabytes(tamanho), 3,MidpointRounding.AwayFromZero) +" MB!";
                }
    
                catch (Exception ex)
                {
                    return "Erro ao receber o ficheiro: " + fileData.FileName + ". Erro: " + ex.Message;
                }
    
    
            }


    based in http://www.dotnetfunda.com/articles/show/2008/upload-a-file-using-aspnet-file-upload-control-and-wcf

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, September 26, 2013 9:51 AM
  • User-488622176 posted

    Always nice to be able to mark your own replies as the solution ;-)

    For your 64Kb limit (I did not find in the original question). What you propose is extremely slow. The windows sizes in WCF can be configured. 64Kb is a default. You can modify your service binding configs as hown in http://stackoverflow.com/questions/884235/wcf-how-to-increase-message-size-quota

    You virtually have no limit. Although : big sizes on slow communication channels require you change timeout values too.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, September 27, 2013 8:27 AM

All replies

  • User836698845 posted

    Solution found.

    New DataContract, with a byte array and not a stream to send the file.

    Then for the 64Kb limitation of data,  in the cliente I send maximum 64Kb each time and when have the total byte array, save the file.

    Tested and working

    Forget to add the code.

     [OperationContract]
            string UploadFileDataTTT(FileData fileData);
     
     [DataContract]
        public class FileData
        {
            [DataMember]
            public string FileName
            {
                get;
                set;
            }
             [DataMember]
            public byte[] BufferData
            {
                get;
                set;
            }
            [DataMember]
            public int FilePosition
            {
                get;
                set;
            }
    
    
        }
    
     public string UploadFileDataTTT(FileData fileData)
            {
                try
                {
                    string directoriaUpload = @"C:\upload\";
                    string FilePath = Path.Combine(directoriaUpload, fileData.FileName);
    
                    if (fileData.FilePosition == 0)
                        File.Create(FilePath).Close();
    
                    long tamanho;
                    using (FileStream fileStream = new FileStream(FilePath, FileMode.Open,
                                         FileAccess.ReadWrite, FileShare.Read))
                    {
    
                        fileStream.Seek(fileData.FilePosition, SeekOrigin.Begin);
                        fileStream.Write(fileData.BufferData, 0, fileData.BufferData.Length);
    
                        tamanho = fileStream.Length;
                    }
                    return "Ficheiro Recebido: " + fileData.FileName + "! Tamanho: " + Math.Round ( ConvertBytesToMegabytes(tamanho), 3,MidpointRounding.AwayFromZero) +" MB!";
                }
    
                catch (Exception ex)
                {
                    return "Erro ao receber o ficheiro: " + fileData.FileName + ". Erro: " + ex.Message;
                }
    
    
            }


    based in http://www.dotnetfunda.com/articles/show/2008/upload-a-file-using-aspnet-file-upload-control-and-wcf

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, September 26, 2013 9:51 AM
  • User-488622176 posted

    Always nice to be able to mark your own replies as the solution ;-)

    For your 64Kb limit (I did not find in the original question). What you propose is extremely slow. The windows sizes in WCF can be configured. 64Kb is a default. You can modify your service binding configs as hown in http://stackoverflow.com/questions/884235/wcf-how-to-increase-message-size-quota

    You virtually have no limit. Although : big sizes on slow communication channels require you change timeout values too.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, September 27, 2013 8:27 AM
  • User836698845 posted

    Illeris, thank you for your comment. As I found the solution for my problem without an answer from other people, I replied only if someone had the same problem to try to guide them, as it worked for me. (Yes, I forgot to add the code, and added it now).

    As for the buffer limit of the 64Kb, there are some limitations on the server side that I'm aware (sort of).

    There are several applications in the server as in quality/testing server, and the free bandwith is floating up and down. I've made some tests up to ~200Kb per packet, and from there I get sometimes packets lost.

    Monday, September 30, 2013 3:50 AM