C# 通过下载连接已拆分的二进制文件

C# 通过下载连接已拆分的二进制文件,c#,asp.net,proxy,C#,Asp.net,Proxy,我正在尝试加入一些在下载过程中拆分的二进制文件。这项要求源于该项目。在本项目中,作者允许您通过提供url下载文件 问题是,我的服务器没有足够的内存来保存大于20兆的文件。因此,为了解决这个问题,我修改了代码,不下载大于10兆的文件,如果文件较大,则允许用户下载前10兆。用户必须继续下载,并希望获得第二个10兆。现在我已经完成了所有这些工作,除了当用户需要加入他们下载的文件时,我最终得到了损坏的文件,据我所知,通过下载添加或删除了一些内容 我目前正在通过读取所有文件,然后将它们写入一个文件来将这些

我正在尝试加入一些在下载过程中拆分的二进制文件。这项要求源于该项目。在本项目中,作者允许您通过提供url下载文件

问题是,我的服务器没有足够的内存来保存大于20兆的文件。因此,为了解决这个问题,我修改了代码,不下载大于10兆的文件,如果文件较大,则允许用户下载前10兆。用户必须继续下载,并希望获得第二个10兆。现在我已经完成了所有这些工作,除了当用户需要加入他们下载的文件时,我最终得到了损坏的文件,据我所知,通过下载添加或删除了一些内容

我目前正在通过读取所有文件,然后将它们写入一个文件来将这些文件连接在一起。这应该可以工作,因为我正在以字节为单位进行读取和写入。这里列出了我用来加入文件的代码

我身上没有atm机的准确代码,只要我一回到家,如果有人愿意帮忙,我就会发布准确的代码

请让我知道我是否遗漏了任何东西,或者是否有更好的方法来做到这一点,即我可以使用什么来替代内存流。我修改的原始项目的源代码可以在这里找到,应该注意的是我使用的是5.0版。我修改的文件名为WebDataCore.cs,我修改了第606行,直到加载了10兆的数据才能继续执行

如果我遗漏了什么,请告诉我


谢谢

您不应该因为内存原因而拆分。。。拆分的原因通常是为了避免在出现故障时重新下载所有内容。如果记忆是一个问题,你是做错了。。。例如,您不应该在内存中缓冲

下载文件的最简单方法是:

using(WebClient client = new WebClient()) {
    client.DownloadFile(remoteUrl, localPath);
}
重新编写拆分/连接代码-问题是,您正在缓冲内存中的所有内容;除非您知道自己有小文件,否则File.ReadAllBytes是一件坏事。你应该拥有的是:

byte[] buffer = new byte[8192]; // why not...
int read;
while((read = inStream.Read(buffer, 0, buffer.Length)) > 0)
{
    outStream.Write(buffer, 0, read);
}
这使用一个适度的缓冲区将数据作为流在两者之间泵送。效率更高。循环说:

尝试读取最多一些数据,即缓冲区大小 这将读取至少1个字节,或者我们已经到达流的末尾 如果我们读了一些东西,就把这么多字节从缓冲区写到输出
您不应该因为内存原因而拆分。。。拆分的原因通常是为了避免在出现故障时重新下载所有内容。如果记忆是一个问题,你是做错了。。。例如,您不应该在内存中缓冲

下载文件的最简单方法是:

using(WebClient client = new WebClient()) {
    client.DownloadFile(remoteUrl, localPath);
}
重新编写拆分/连接代码-问题是,您正在缓冲内存中的所有内容;除非您知道自己有小文件,否则File.ReadAllBytes是一件坏事。你应该拥有的是:

byte[] buffer = new byte[8192]; // why not...
int read;
while((read = inStream.Read(buffer, 0, buffer.Length)) > 0)
{
    outStream.Write(buffer, 0, read);
}
这使用一个适度的缓冲区将数据作为流在两者之间泵送。效率更高。循环说:

尝试读取最多一些数据,即缓冲区大小 这将读取至少1个字节,或者我们已经到达流的末尾 如果我们读了一些东西,就把这么多字节从缓冲区写到输出
该示例将每个区块加载到内存中,您可以执行以下操作:

int bufSize = 1024 * 32;
byte[] buffer = new byte[bufSize];

using (FileStream outputFile = new FileStream(OutputFileName, FileMode.OpenOrCreate,
FileAccess.Write, FileShare.None, bufSize))
{
    foreach (string inputFileName in inputFiles)
    {
        using (FileStream inputFile = new FileStream(inputFileName, FileMode.Append,
            FileAccess.Write, FileShare.None, buffer.Length))
    {
    int bytesRead = 0;

    while ((bytesRead = inputFile.Read(buffer, 0, buffer.Length)) != 0)
    {
        outputFile.Write(buffer, 0, bytesRead);
    }
}

该示例将每个区块加载到内存中,您可以执行以下操作:

int bufSize = 1024 * 32;
byte[] buffer = new byte[bufSize];

using (FileStream outputFile = new FileStream(OutputFileName, FileMode.OpenOrCreate,
FileAccess.Write, FileShare.None, bufSize))
{
    foreach (string inputFileName in inputFiles)
    {
        using (FileStream inputFile = new FileStream(inputFileName, FileMode.Append,
            FileAccess.Write, FileShare.None, buffer.Length))
    {
    int bytesRead = 0;

    while ((bytesRead = inputFile.Read(buffer, 0, buffer.Length)) != 0)
    {
        outputFile.Write(buffer, 0, bytesRead);
    }
}

最后,我发现通过使用FTP请求,我能够解决内存问题,并且文件保存正确


感谢所有的帮助

最后,我发现通过使用FTP请求,我能够解决内存问题,并且正确保存了文件


感谢所有帮助

buffer.Write中的长度应为bytesRead,否则将损坏;将bytesRead初始化为0是没有意义的-无论如何,它会在下一行重置感谢文件流的想法,我已经尝试过这个方法,并使它工作了,除了我可能超过我的托管限制:buffer.Length in Write应该是bytesRead-否则会损坏;将ByteRead初始化为0是没有意义的-它会在下一行被重置感谢文件流的想法,我已经尝试过这个方法,并让它工作了,只是我可能会超过我的托管限制:谢谢,伙计,您的代码看起来很完美,但我不确定如何将其实现到项目中,因为流所在的位置和数据写入的位置位于项目的另一端。我可以再请求一点帮助吗。嗨,我已经按照你的建议进行了测试和更改,它在我的台式电脑上运行良好,但一旦我部署到服务器上,它就失败了,你有什么其他想法可以让我试试,因为我完全不知道:很抱歉,基本上,它仍然会抛弃记忆,除了你是否使用了记忆流?仍然在记忆中——或者你在转移
两个IO流之间的ng?谢谢,伙计,你的代码看起来很完美,但我不确定如何将其实现到项目中,因为流所在的位置和数据写入的位置在项目的另一端。我可以再请求一点帮助吗。嗨,我已经按照你的建议进行了测试和更改,它在我的台式电脑上运行良好,但一旦我部署到服务器上,它就失败了,你有什么其他想法可以让我试试,因为我完全不知道:很抱歉,基本上,它仍然会抛弃记忆,除了你是否使用了记忆流?仍在内存中-还是在两个IO流之间传输?