C# 如何将文件拆分为多个部分并下载
我正在为c#开发一个拆分下载程序。它可以很好地下载(因此逻辑是有效的),但问题是它下载的任何文件都会被破坏。我不知道如何修理它。代码如下:C# 如何将文件拆分为多个部分并下载,c#,http,web,download,C#,Http,Web,Download,我正在为c#开发一个拆分下载程序。它可以很好地下载(因此逻辑是有效的),但问题是它下载的任何文件都会被破坏。我不知道如何修理它。代码如下: private void mergeClean() { const int chunkSize = 1 * 1024; // 2KB using (var output = File.Create("output.jpg")) { foreach (var file in Fil
private void mergeClean()
{
const int chunkSize = 1 * 1024; // 2KB
using (var output = File.Create("output.jpg"))
{
foreach (var file in Files)
{
using (var input = File.OpenRead(file))
{
var buffer = new byte[chunkSize];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
}
}
foreach (var file in Files)
{
File.Delete(file);
}
}
private void SaveFileStream(String path, Stream stream)
{
var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
stream.CopyTo(fileStream);
fileStream.Dispose();
}
public void SplitDownload(string URL)
{
System.Net.WebRequest req = System.Net.HttpWebRequest.Create(URL);
req.Method = "HEAD";
System.Net.WebResponse resp = req.GetResponse();
var responseLength = double.Parse(resp.Headers.Get("Content-Length"));
var partSize = Math.Ceiling(responseLength / 10);
var previous = 0;
for (int i = (int)partSize; i <= responseLength; i = i + (int)partSize)
{
Thread t = new Thread(() => Download(URL, previous, i));
t.Start();
t.Join();
previous = i;
}
mergeClean();
}
private void Download(string URL, int Start, int End)
{
Console.WriteLine(String.Format("{0},{1}", Start, End));
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(URL);
myHttpWebRequest.AddRange(Start, End);
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
Stream streamResponse = myHttpWebResponse.GetResponseStream();
String name = GenerateTempName();
SaveFileStream(name, streamResponse);
Files.Add(name);
}
private void mergeClean()
{
常量int chunkSize=1*1024;//2KB
使用(var output=File.Create(“output.jpg”))
{
foreach(文件中的var文件)
{
使用(var input=File.OpenRead(File))
{
var buffer=新字节[chunkSize];
int字节读取;
而((bytesRead=input.Read(buffer,0,buffer.Length))>0)
{
输出写入(缓冲区,0,字节读取);
}
}
}
}
foreach(文件中的var文件)
{
文件。删除(文件);
}
}
私有void SaveFileStream(字符串路径、流)
{
var fileStream=newfilestream(路径,FileMode.Create,FileAccess.Write);
CopyTo(fileStream);
Dispose();
}
公共void SplitDownload(字符串URL)
{
System.Net.WebRequest req=System.Net.HttpWebRequest.Create(URL);
请求方法=“头”;
System.Net.WebResponse resp=req.GetResponse();
var responseLength=double.Parse(resp.Headers.Get(“内容长度”));
var零件尺寸=数学上限(响应长度/10);
var-previous=0;
对于(inti=(int)partSize;我下载(URL,previous,i));
t、 Start();
t、 Join();
先前=i;
}
mergeClean();
}
私有void下载(字符串URL、int Start、int End)
{
WriteLine(String.Format(“{0},{1}”,Start,End));
HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create(URL);
myHttpWebRequest.AddRange(开始、结束);
HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();
streamResponse=myHttpWebResponse.GetResponseStream();
字符串名称=GenerateTempName();
SaveFileStream(名称、streamResponse);
文件。添加(名称);
}
下面是一个示例,说明它的作用:
更新代码:
static string GenerateTempName(int start)
{
String name = String.Format("{0:D6}.tmp", start);
return name;
}
static public List<string> Files = new List<string>();
static private void mergeClean()
{
Files.Sort();
const int chunkSize = 1 * 1024; // 2KB
using (var output = File.Create("output.jpg"))
{
foreach (var file in Files)
{
using (var input = File.OpenRead(file))
{
var buffer = new byte[chunkSize];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
}
}
foreach (var file in Files)
{
File.Delete(file);
}
}
静态字符串GenerateTempName(int start)
{
String name=String.Format(“{0:D6}.tmp”,start);
返回名称;
}
静态公共列表文件=新列表();
静态私有void mergeClean()
{
Sort()文件;
常量int chunkSize=1*1024;//2KB
使用(var output=File.Create(“output.jpg”))
{
foreach(文件中的var文件)
{
使用(var input=File.OpenRead(File))
{
var buffer=新字节[chunkSize];
int字节读取;
而((bytesRead=input.Read(buffer,0,buffer.Length))>0)
{
输出写入(缓冲区,0,字节读取);
}
}
}
}
foreach(文件中的var文件)
{
文件。删除(文件);
}
}
您需要以正确的顺序从片段中重新组合文件-当前代码创建随机文件名,即使项目添加到文件列表中,由于片段下载完成的时间不可预测,它们也会以随机顺序添加
可能的修复方法:使用块开始偏移量作为文件名String name=String.Format(“文件{0:D6}.tmp”,start)
的一部分,并按名称对文件进行排序,然后再将其合并回去
请注意,
{0:D6}
用于将索引填充为0,以便于按名称排序,并避免使用自然排序代码。如何确保以正确的顺序读取/重建文件?下载每个文件后,临时名称将添加到名称数组中。mergeclean函数遍历此数组并连接文件。因此,它按数组中文件的顺序合并。但是因为它是按正确的顺序下载的。我猜它正在以正确的顺序合并@Ronbeyer在发送前创建文件的校验和,然后在下载后确认。我还注意到,您正在使用几个对象(WebResponse、Stream),这些对象不在使用块的中。异常将使这些处于错误状态。const int chunkSize=1*1024;//2KB
;-)好的,我接受了你的建议,现在正在对数组进行排序,然后再合并它。但问题仍然存在,它下载的图像仍然损坏。还有其他想法吗?@Chocoloco“你应该发送previous+1,而不是previous“-{0,10},{10,20},。。。而不是{0,9},{10,19},。。。