Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#中通过网络发送大文件的好方法?_C#_Networking_File Transfer - Fatal编程技术网

在C#中通过网络发送大文件的好方法?

在C#中通过网络发送大文件的好方法?,c#,networking,file-transfer,C#,Networking,File Transfer,我正在尝试构建一个应用程序,该应用程序可以从网络中另一台机器上运行的服务请求文件。这些文件可能相当大(有时超过500mb)。我正在考虑通过TCP发送它,但我担心它可能需要将整个文件存储在内存中 可能只有一个客户机。复制到共享目录也是不可接受的。唯一需要的通信是客户端说“gimmeyz”,服务器发送它(以及确保正确执行此操作所需的一切) 有什么建议吗?使用TransmitFile(这是一个Win32函数;可能也是.NET库的一种方法) 您可以使用.NET中的套接字传输文件和数据。如果FTP是一个选

我正在尝试构建一个应用程序,该应用程序可以从网络中另一台机器上运行的服务请求文件。这些文件可能相当大(有时超过500mb)。我正在考虑通过TCP发送它,但我担心它可能需要将整个文件存储在内存中

可能只有一个客户机。复制到共享目录也是不可接受的。唯一需要的通信是客户端说“gimmeyz”,服务器发送它(以及确保正确执行此操作所需的一切)


有什么建议吗?

使用
TransmitFile
(这是一个Win32函数;可能也是.NET库的一种方法)

您可以使用.NET中的套接字传输文件和数据。

如果FTP是一个选项,那么为了简单起见,我会选择它。否则,你将进入TCP/IP套接字编程的世界。

你可能要考虑。 这里有一个更简单的方法。使用BITS(后台智能传输服务)。它已经内置在WinXP和Vista中。这基本上就是驱动Windows更新的原因

下面是一个很好的托管位包装器,有人编写了它,以及如何使用它


如果计算机上物理上存在文件,为什么不将它们放在文件夹中,将该文件夹设置为IIS中的虚拟目录,并使用基于内容的路由和/或URL重写将请求路由到它们。

通过开源库使用FTP。快速而简单。

本文可能会对您有所帮助。它是关于在.NET中发送大文件的。 检查链接:


小心使用钻头。这是一个非常好的协议,但不是windows update程序的关键部分。我们发现几乎没有一个公司客户允许比特更新到他们的机器上;因此,我们无法构建一个依赖于它的应用程序。

就我个人而言,我会寻求一种兼顾速度、可靠性和经济性的代码,因此我会将其建立在TCP网络流的基础上。代码的客户端如下所示:

internal class Client
{
    private FileStream _fs;     
    private long _expectedLength;

    public void GetFileFromServer(string localFilename)
    {            
        if (File.Exists(localFilename))
            File.Delete(localFilename);

        _fs = new FileStream(localFilename, FileMode.Append);

        var ipEndpointServer = new IPEndPoint(IPAddress.Parse({serverIp}), {serverPort});

        // an object that wraps tcp client
        var client = new TcpClientWrapper(ipEndpointServer, "");
        client.DataReceived += DataReceived;
    }

    private void DataReceived(object sender, DataReceivedEventArgs e)
    {
        var data = e.Data;

        // first packet starts with 4 bytes dedicated to the length of the file
        if (_expectedLength == 0)
        {
            var headerBytes = new byte[4];
            Array.Copy(e.Data, 0, headerBytes, 0, 4);
            _expectedLength = BitConverter.ToInt32(headerBytes, 0);
            data = new byte[e.Data.Length - 4];
            Array.Copy(e.Data, 4, data, 0, data.Length);
        }

        _fs.WriteAsync(e.Data, 0, e.Data.Length);

        if (_fs.Length >= _expectedLength)
        {                                
            // transfer has finished
        }
    }
}
_tcp = new Net.TcpClient();
_tcp.Connect(remoteEp);
_stream = _tcp.GetStream();
_stream.BeginRead(_receivedData, 0, _receivedData.Length, DataReceivedAsync, null);
然后有一个服务器类来服务该文件。请注意,整个文件没有加载到内存中,而是从
FileStream
中分块读取

internal class Server
{
    private TcpServer _tcpServer;
    private NetworkStream _stream;        

    public void StartServer()
    {
        // fire up a simple Tcp server
        _tcpServer = new TcpServer({serverPort}, "test");
        _tcpServer.ClientConnected += ClientConnected;
    }

    private void ClientConnected(object sender, TcpClientConnectedEventArgs e)
    {            
        // an incoming client has been detected ... send the file to that client!
        _stream = e.Client.GetStream();
        SendFileToClient({pathToFile});
    }

    private void SendFileToClient(string pathToFile)
    {
        // open the file as a stream and send in chunks
        using (var fs = new FileStream(pathToFile, FileMode.Open))
        {
            // send header which is file length
            var headerBytes = new byte[4];
            Buffer.BlockCopy(BitConverter.GetBytes(fs.Length + 4), 0, headerBytes, 0, 4);
            _stream.Write(headerBytes, 0, 4);

            // send file in block sizes of your choosing
            var buffer = new byte[100000];
            int bytesRead = 0;
            while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                _stream.Write(buffer, 0, bytesRead);
            }
            _stream.Flush();
        }
    }
}
TCPClientRapper几乎是锅炉板代码,带有
System.Net.Sockets.TcpClient
对象和底层
NetworkStream
对象。我其实也不需要发布这篇文章,但为了给大家一些提示,这个结构包含如下内容:

internal class Client
{
    private FileStream _fs;     
    private long _expectedLength;

    public void GetFileFromServer(string localFilename)
    {            
        if (File.Exists(localFilename))
            File.Delete(localFilename);

        _fs = new FileStream(localFilename, FileMode.Append);

        var ipEndpointServer = new IPEndPoint(IPAddress.Parse({serverIp}), {serverPort});

        // an object that wraps tcp client
        var client = new TcpClientWrapper(ipEndpointServer, "");
        client.DataReceived += DataReceived;
    }

    private void DataReceived(object sender, DataReceivedEventArgs e)
    {
        var data = e.Data;

        // first packet starts with 4 bytes dedicated to the length of the file
        if (_expectedLength == 0)
        {
            var headerBytes = new byte[4];
            Array.Copy(e.Data, 0, headerBytes, 0, 4);
            _expectedLength = BitConverter.ToInt32(headerBytes, 0);
            data = new byte[e.Data.Length - 4];
            Array.Copy(e.Data, 4, data, 0, data.Length);
        }

        _fs.WriteAsync(e.Data, 0, e.Data.Length);

        if (_fs.Length >= _expectedLength)
        {                                
            // transfer has finished
        }
    }
}
_tcp = new Net.TcpClient();
_tcp.Connect(remoteEp);
_stream = _tcp.GetStream();
_stream.BeginRead(_receivedData, 0, _receivedData.Length, DataReceivedAsync, null);
DataReceivedAsync
方法是样板套接字数据处理,将引发一个事件,以便将接收到的数据共享回使用者(在本例中为客户端):

将数据从包装器发送回客户端的事件:

public EventHandler<DataReceivedEventArgs> DataReceived;
public class DataReceivedEventArgs : EventArgs
{
    public DataReceivedEventArgs(byte[] data) { Data = data; }
    public byte[] Data { get; }
}
已接收公共事件处理程序数据;
公共类DataReceivedEventArgs:EventArgs
{
public DataReceivedEventArgs(字节[]数据){data=data;}
公共字节[]数据{get;}
}

这是一个很好的解决方案