3

I have a WCF Service, which uploads the document using Stream class.

Now after this, i want to get the Size of the document(Length of Stream), to update the fileAttribute for FileSize.

But doing this, the WCF throws an exception saying

Document Upload Exception: System.NotSupportedException: Specified method is not supported.
   at System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream.get_Length()
   at eDMRMService.DocumentHandling.UploadDocument(UploadDocumentRequest request)

Can anyone help me in solving this.

Kishore Kumar
  • 12,675
  • 27
  • 97
  • 154

2 Answers2

6

Now after this, i want to get the Size of the document(Length of Stream), to update the fileAttribute for FileSize.

No, don't do that. If you are writing a file, then just write the file. At the simplest:

using(var file = File.Create(path)) {
    source.CopyTo(file);
}

or before 4.0:

using(var file = File.Create(path)) {
    byte[] buffer = new byte[8192];
    int read;
    while((read = source.Read(buffer, 0, buffer.Length)) > 0) {
        file.Write(buffer, 0, read);
    }
}

(which does not need to know the length in advance)

Note that some WCF options (full message security etc) require the entire message to be validated before processing, so can never truly stream, so: if the size is huge, I suggest you instead use an API where the client splits it and sends it in pieces (which you then reassemble at the server).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • i cant use .net 4.0, i am using 3.5 – Kishore Kumar Aug 07 '12 at 15:15
  • If you don't have `CopyTo` then implement your own `byte[] buffer = new byte[4096]; for(int byteCount = source.Read(buffer, 0, 4096); byteCount != 0; byteCount = source.Read(buffer, 0, 4096)file.Write(buffer, 0, byteCount);` 4096 is a memory page size, so it tends to do well, you don't want to go beyond double that at the most or you're wasting memory for no gain. – Jon Hanna Aug 07 '12 at 15:20
  • 1
    @TheIndianProgrammmer (sigh) well that's about 4 lines of code to do manually... one moment... – Marc Gravell Aug 07 '12 at 15:20
  • i am not writing file anywhere.. i am more concerened of knowing the fileSize from stream – Kishore Kumar Aug 07 '12 at 15:26
  • How can you have a fileSize, without a file? – Jon Hanna Aug 07 '12 at 15:26
  • 2
    @TheIndianProgrammmer in that case, *you're using the stream wrong*. For example: somebody gives you the business end of a hosepipe - now answer: how much water is there? the only way to find out is to *let it flow*. You attach a meter, then: either pour it away and it is gone for good, or you have to buffer it all in a giant bucket somewhere. Most streams do not *know* their length. – Marc Gravell Aug 07 '12 at 15:28
0

If the stream doesn't support seeking you cannot find its length using Stream.Length

The alternative is to copy the stream to a byte array and find its cumulative length. This involves processing the whole stream first , if you don't want this, you should add a stream length parameter to your WCF service interface

parapura rajkumar
  • 24,045
  • 1
  • 55
  • 85
  • getting byte[] is heavy process if the filesize is large – Kishore Kumar Aug 07 '12 at 14:54
  • @TheIndianProgrammmer which is exactly why you should treat it as a `Stream` ;p You don't need to know the length to do that. Alternatively: the caller could chunk the file and send it in multiple pieces. – Marc Gravell Aug 07 '12 at 15:06
  • Exactly, if you're going to save it as a file, what do you care what size it is before? You don't want to use more than 4-8k chunks in memory at a time. If you want to set a max file size, then do it by copying up to your maximum, and then deleting the file and aborting if you hit it. – Jon Hanna Aug 07 '12 at 15:21