file upload download using WCF rest

11,282

Solution 1

You can make this far simpler:

public void Upload(Stream fileStream)
{
    using (var output = File.Open(path, FileMode.Create))
        fileStream.CopyTo(output);
}

The problem with your existing code is that you call ReadByte and read the entire input stream, then try to read it again (but it's now at the end). This means your second reads will all fail (the read variable will be 0 in your loop, and immediately break out) since the stream is now at its end.

Solution 2

Here I have created a WCF REST service. Service.svc.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace UploadSvc
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
                 InstanceContextMode = InstanceContextMode.PerCall,
                 IgnoreExtensionDataObject = true,
                 IncludeExceptionDetailInFaults = true)]    
      public class UploadService : IUploadService
    {

        public UploadedFile Upload(Stream uploading)
        {
            var upload = new UploadedFile
            {
                FilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())
            };

            int length = 0;
            using (var writer = new FileStream(upload.FilePath, FileMode.Create))
            {
                int readCount;
                var buffer = new byte[8192];
                while ((readCount = uploading.Read(buffer, 0, buffer.Length)) != 0)
                {
                    writer.Write(buffer, 0, readCount);
                    length += readCount;
                }
            }

            upload.FileLength = length;

            return upload;
        }

        public UploadedFile Upload(UploadedFile uploading, string fileName)
        {
            uploading.FileName = fileName;
            return uploading;
        }
    }
}

Web.config

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime executionTimeout="100000" maxRequestLength="20000000"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 maxReceivedMessageSize="2147483647"
                 transferMode="Streamed"
                 sendTimeout="00:05:00" closeTimeout="00:05:00" receiveTimeout="00:05:00">
          <readerQuotas  maxDepth="2147483647"
                         maxStringContentLength="2147483647"
                         maxArrayLength="2147483647"
                         maxBytesPerRead="2147483647"
                         maxNameTableCharCount="2147483647"/>
          <security mode="None" />
        </binding>
      </webHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="defaultEndpointBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="defaultServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="UploadSvc.UploadService" behaviorConfiguration="defaultServiceBehavior">
        <endpoint address="" behaviorConfiguration="defaultEndpointBehavior"
          binding="webHttpBinding" contract="UploadSvc.IUploadService"/>
      </service>
    </services>    
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>

Consumer.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Cache;
using System.Text;

namespace UploadSvcConsumer
{
    class Program
    {
        static void Main(string[] args)
        {
            //WebClient client = new WebClient();
            //client.UploadData("http://localhost:1208/UploadService.svc/Upload",)
            //string path = Path.GetFullPath(".");
            byte[] bytearray=null ;
            //throw new NotImplementedException();
            Stream stream =
                new FileStream(
                    @"C:\Image\hanuman.jpg"
                    FileMode.Open);
                stream.Seek(0, SeekOrigin.Begin);
                bytearray = new byte[stream.Length];
                int count = 0;
                while (count < stream.Length)
                {
                    bytearray[count++] = Convert.ToByte(stream.ReadByte());
                }

            string baseAddress = "http://localhost:1208/UploadService.svc/";
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(baseAddress + "Upload");
            request.Method = "POST";
            request.ContentType = "text/plain";
            request.KeepAlive = false;
            request.ProtocolVersion = HttpVersion.Version10;
            Stream serverStream = request.GetRequestStream();
            serverStream.Write(bytearray, 0, bytearray.Length);
            serverStream.Close();
            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                int statusCode = (int)response.StatusCode;
                StreamReader reader = new StreamReader(response.GetResponseStream());

            }

        }
    }
}
Share:
11,282

Related videos on Youtube

user20358
Author by

user20358

Updated on October 21, 2022

Comments

  • user20358
    user20358 over 1 year

    I am using .net 4.0 and trying to upload a file using a rest wcf service with a method called upload and download it using the same rest service using a method called download. There is a console application that sends the stream data to the wcf service and the same console app downloads from the service. The console application uses WebChannelFactory to connect and work with the service.

    Here is a code from the console app

                StreamReader fileContent = new StreamReader(fileToUpload, false);
                webChannelServiceImplementation.Upload(fileContent.BaseStream );
    

    This is the wcf service code

    public void Upload(Stream fileStream)
    {
            long filebuffer  = 0;
            while (fileStream.ReadByte()>0)
            {
                filebuffer++;
            }
    
            byte[] buffer = new byte[filebuffer];
            using (MemoryStream memoryStream = new MemoryStream())
            {
                int read;
    
                while ((read = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    memoryStream.Write(buffer, 0, read);
    
                }
                File.WriteAllBytes(path, buffer);
            }
    }
    

    Now at this step when I examine the file, I notice it has the same size in Kilobytes as the original file that was sent from the console app, but when I open the file, it has no content. The file can be any file type, be it an excel or word document, it still comes up to the server as an empty file. Where is all the data gone?

    The reason I am doing a fileStream.ReadByte()>0 is because I read somewhere that when transfering over the network, the buffer length cant be found out (which is why I was getting an exception when trying to get the length of the stream in the service upload method). This is why I dont use byte[] buffer = new byte[32768]; as in shown in many online examples where the byte array is fixed.

    While downloading from the service I use this code on the wcf service side

        public Stream Download()
        {
            return new MemoryStream(File.ReadAllBytes("filename"));
        }
    

    And on the console app side I have

            Stream fileStream = webChannelServiceImplementation.Download();
    
            //find size of buffer
            long size= 0;
            while (fileStream .ReadByte() > 0)
            {
                size++;
            }
            byte[] buffer = new byte[size];
    
            using (Stream memoryStream = new MemoryStream())
            {
                int read;
                while ((read = fileContents.Read(buffer, 0, buffer.Length)) > 0)
                {
                    memoryStream.Write(buffer, 0, read);
                }
    
                File.WriteAllBytes("filename.doc", buffer);
            }
    

    Now this downloaded file is also blank, because its downloading the file I uploaded earlier using the upload code above, and its only 16 KB in size even though the uploaded file was 200 KB in size.

    What is wrong with my code? Any help appreciated.

  • user20358
    user20358 over 10 years
    Thanks. I will try that out. Why do you suppose the download is only 16kb and not the entire 200kb Ijust uploaded?
  • Reed Copsey
    Reed Copsey over 10 years
    @user20358 If you uploaded via the mechanism above, it's going to have made a 0 byte file. I'd fix the upload first, tehn focus on the download portion...
  • Reed Copsey
    Reed Copsey over 10 years
    @user20358 You can write hte download the same way
  • user20358
    user20358 over 10 years
    Thanks. I did the same. There was some other issue with the download.