Example of resumable download of a large WCF File

Source: Internet
Author: User
Full download: http://files.cnblogs.com/qldsrx/FilesManager.rar

No complete project is provided for the content of the clips sent before.CodeA lot of people have come to work out, so it took four days to debug a complete Demo project. In addition, if it is a WCF Service carried by IIS, it is recommended to write a class that inherits ihttphandler to implement it directly, which is more efficient and more fine-grained, using the WCF Service is just a compromise without using IIS. Note: The. net4.0 or later version must be installed.

 

First, let's briefly introduce thisProgramImplemented functions:

A server uses the WCF self-bearer mode. By default, the rest mode is used. Http download is provided directly, and other modes such as net TCP can be enabled. During HTTP download, ie does not support resumable data transfer. In the download software, only the network conveyor belt supports resumable data transfer, the main reason is that my WCF Service uses the stream mode for transmission. The client software cannot obtain the total length of the data to be received. I think resumable data transfer is not supported, so I will not directly consider resumable data transfer, however, the network conveyor belt is different. It can continue to try to resume the transfer request to see how the server responds. Therefore, only the network conveyor belt supports resumable transfer. To solve the problem that the download tool does not support resumable data transfer, I added an HTTP Download Method to the client. Enter the HTTP Download Method to start the download and resume the download, restore from the breakpoint. In addition, the direct program download method is provided. This function is simple, and the client cannot interrupt the download. Unless the network is interrupted, you can try again and resume the download from the breakpoint, however, manual interruption is not acceptable. This is caused by the password encapsulation of the WCF message mechanism. We cannot actively interrupt message transmission (the file is being downloaded to receive messages ).

 

This is the server interface

 

After you click "enable service", the button changes to "running". When the service is opened, the listening port of the service is 12251 by default. If you do not want to use this port, you can enable source code recompilation, there is a baseaddress variable in form1. You can modify the variable or set it to the configuration file. This is not a problem for demonstration projects.

After the service is enabled, click "file directory" to set the directory that currently provides the file download service. The current directory will display the current location. Click "generate link". The file list is displayed, with only one layer. Recursive processing is not performed. Only files generated after a link can be downloaded. Otherwise, all files are accessed illegally and are not downloaded. This ensures system security. Click "Copy selected link". You can copy the download link to the clipboard. You can download the link directly from IE.

Click the HTTP help link to view detailed service call instructions. If you want to change the help, you can modify the config file.

 

This is the client interface:

 

After entering the service address, click "Get download list". Once the download list is obtained successfully, the service address cannot be changed. In this case, the "Download selected file" function is directly used, and the file is directly downloaded through the WCF interface function, which is irrelevant to the underlying transmission protocol. If you first copy the selected link and then open the HTTP download window, the file will be downloaded through the HTTP address, which is downloaded through the resf service provided by WCF.

 

The whole demonstration project involves a lot of knowledge points, so it took a long time. The following briefly describes several key points involved in the project.

1. Message stream encapsulation.

I have previously written an article about custom file streams. Now I think it is more mature. Using custom read streams, You can encapsulate any streams, such as memory streams, it is possible that the content to be transmitted must be pre-processed, processed, and transmitted. In this way, the memory stream must be encapsulated for transmission. Custom read stream (read-only) ///   <Summary>
/// Custom read stream (read-only)
///   </Summary>
Internal Class Cusstreamreader: Stream
{
Long _ Endposition; // End position
Stream innerstream;
///   <Summary>
/// The parameter is the breakpoint of the current stream.
///   </Summary>
Public Event Action < Long > Reading;

///   <Summary>
/// Use the original stream directly.
///   </Summary>
///   <Param name = "stream"> Original stream </Param>
Public Cusstreamreader (Stream)
{
This . Innerstream = stream;
_ Endposition = stream. length;
}
///   <Summary>
/// Use the current stream position and specify the length to initialize the custom stream
///   </Summary>
///   <Param name = "stream"> Original stream </Param>
///   <Param name = "count"> Length </Param>
Public Cusstreamreader (Stream stream, Long Count)
{
This . Innerstream = stream;
_ Endposition = stream. Position + count;
If (_ Endposition> stream. length)
_ Endposition = stream. length;
}
///   <Summary>
/// Specify the initial position and length to initialize the custom stream
///   </Summary>
///   <Param name = "stream"> Original stream </Param>
///   <Param name = "offset"> Initial Location </Param>
///   <Param name = "count"> Length </Param>
Public Cusstreamreader (Stream stream, Long Offset, Long Count)
{
Stream. Position = offset> stream. length? Stream. Length: offset;
This . Innerstream = stream;
_ Endposition = offset + count;
If (_ Endposition> stream. length)
_ Endposition = stream. length;
}
///   <Summary>
/// Reads the specified length from the custom stream to the array, but does not exceed the length set during initialization.
///   </Summary>
///   <Returns> Number of bytes read </Returns>
Public Override Int Read ( Byte [] Array, Int Offset, Int Count)
{
Int Readcount = 0 ;
If (Position + count> This . _ Endposition)
Readcount = innerstream. Read (array, offset ,( Int )( This . _ Endposition-position ));
Else
Readcount = innerstream. Read (array, offset, count );
If (Reading! = Null )
Reading (position );
Return Readcount;
}
///   <Summary>
/// Read a byte from a custom stream, but it cannot exceed the length set during initialization.
///   </Summary>
///   <Returns> Read bytes.-1 is returned if not found. </Returns>
Public Override Int Readbyte ()
{
If (Position> = This . _ Endposition)
Return - 1 ;
Else
Return Base . Readbyte ();
}

Public override bool Canread
{< br> Get { return innerstream. canread ;}< BR >}

Public override bool canseek
{< br> Get { return false ;}< BR >}

Public override bool canwrite
{< br> Get { return false ;}< BR >}

Public Override VoidFlush ()
{
Throw NewNotimplementedexception ();
}

///   <Summary>
/// The remaining length of the custom stream.
///   </Summary>
Public Override Long Length
{
Get { Return _ Endposition-innerstream. position ;}
}

///   <Summary>
/// Customizes the stream position and returns the original stream position.
///   </Summary>
Public Override Long Position
{
Get
{
Return Innerstream. position;
}
Set
{
Throw New Notimplementedexception ();
}
}

Public override long seek ( long offset, seekorigin origin)
{< br> throw New notimplementedexception ();
}

Public override void setlength ( long value)
{< br> throw New notimplementedexception ();
}

Public Override VoidWrite (Byte[] Buffer,IntOffset,IntCount)
{
Throw NewNotimplementedexception ();
}
}

 

Call Code Cusstreamreader FS = New Cusstreamreader ( New Filestream (file. filepath, filemode. Open, fileaccess. Read, fileshare. Read), offset, count );
FS. Reading + = (t) =>
{
// Speed limit code, which can be removed or precisely controlled during actual use
Thread. Sleep ( 300 );
Console. writeline (t );
};

This reading event is very important. We can use it to speed up or display the transmission status, showing the number of bytes currently passed.

 

Ii. Exception Handling.

For illegal requests, an error exception must be returned, while the default error exception handling in WCF is different from that in HTTP. If HTTP webrequest is used for download, the error exception cannot be directly captured, after reading the relevant information, I found that exceptions of the webexception type should be caught and then processed specially .. In net4.0, you can directly throw a webfaultexception <t> type exception, so that the exception information can be easily handled during HTTP webrequest requests, but this brings another problem. If you support access in servicemodel at the same time, this webfaultexception exception will fail to get the content, and only the error code such as (404) can be obtained. Obviously, this will not work. After repeated debugging, the server should throw a faultexception exception, in this way, access in servicemodel can directly capture exceptions, and httpwebrequest can also analyze error information. The core code is as follows:

Exception capture during Web requests Try
{

}
Catch (Webexception ex)
{
VaR Errresp = ex. Response As Httpwebresponse;
Using ( VaR Stream = errresp. getresponsestream ())
{
String Message = Null ;
Using ( VaR Sr = New Streamreader (Stream ))
{
Message = Sr. readtoend ();
VaR Match = RegEx. Match (message, " (? Is )(? <= <Text [^>] *> ).*(? = </Text>) " );
If (Match. Success)
{
Message = match. value;
}
}
MessageBox. Show (Message );
}
}

 

I will not talk about other things. Although I am only a demo project, I have a lot of knowledge points.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.