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.
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.
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());
}
}
}
}