C#集成FastDFS断点续传
C#集成FastDFS断点续传
参考
.net版本FastDFS客户端v5.05。
https://github.com/zhouyh362329/fastdfs.client.net
FastDFS环境准备。
http://www.cnblogs.com/ddrsql/p/7118695.html
webuploader。
http://fex.baidu.com/webuploader/
普通方式下载
非断点续传方式下载。
/// <summary>
/// 普通下载
/// </summary>
public void Download()
{
string fileName = "下载测试test.txt";
string filePath = Server.MapPath("/File/test.txt"); System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath); if (fileInfo.Exists == true)
{
const long ChunkSize = ;
byte[] buffer = new byte[ChunkSize]; Response.Clear();
System.IO.FileStream iStream = System.IO.File.OpenRead(filePath);
long dataLengthToRead = iStream.Length;//获取下载的文件总大小
Response.ContentEncoding = Encoding.UTF8;
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
while (dataLengthToRead > && Response.IsClientConnected)
{
Thread.Sleep();
int lengthRead = iStream.Read(buffer, , Convert.ToInt32(ChunkSize));//读取的大小
Response.OutputStream.Write(buffer, , lengthRead);
Response.Flush();
dataLengthToRead -= lengthRead;
}
Response.Close();
}
}
下载完成前客户端不知道文件大小。

MVC FastDFS 断点续传方式下载
断点续传几个关键Header属性:
Request
If-Range、Range
Response
StatusCode = 206
Accept-Ranges、ETag、Content-Length、Content-Range
/// <summary>
/// FastDFS下载文件,断点续传
/// </summary>
/// <returns></returns>
public bool DownloadByFDFS()
{
string group_name = "group1";
string remote_filename = "M00/00/00/CgEG1FlWChOEHXNFAAAAAEFinIM178.txt";
string fileName = "测试.txt";
long length = ; long speed = * ;
bool ret = true;
try
{
#region--验证:HttpMethod,请求的文件是否存在
switch (Request.HttpMethod.ToUpper())
{ //目前只支持GET和HEAD方法
case "GET":
case "HEAD":
break;
default:
Response.StatusCode = ;
return false;
}
#endregion #region 定义局部变量
long startBytes = ;
int packSize = * ; //分块读取,每块10K bytes
long fileLength = length;// myFile.Length; int sleep = (int)Math.Ceiling(1000.0 * packSize / speed);//毫秒数:读取下一数据块的时间间隔
string lastUpdateTiemStr = "2017-07-18 11:57:54";
string eTag = HttpUtility.UrlEncode(fileName, Encoding.UTF8) + lastUpdateTiemStr;//便于恢复下载时提取请求头;
#endregion #region--验证:文件是否太大,是否是续传,且在上次被请求的日期之后是否被修改过--------------
//if (myFile.Length > Int32.MaxValue)
//{//-------文件太大了-------
// Response.StatusCode = 413;//请求实体太大
// return false;
//} if (Request.Headers["If-Range"] != null)//对应响应头ETag:文件名+文件最后修改时间
{
//----------上次被请求的日期之后被修改过--------------
if (Request.Headers["If-Range"].Replace("\"", "") != eTag)
{//文件修改过
Response.StatusCode = ;//预处理失败
return false;
}
}
#endregion try
{
#region -------添加重要响应头、解析请求头、相关验证-------------------
Response.Clear();
Response.Buffer = false;
//Response.AddHeader("Content-MD5", GetMD5Hash(myFile));//用于验证文件
Response.AddHeader("Accept-Ranges", "bytes");//重要:续传必须
Response.AppendHeader("ETag", "\"" + eTag + "\"");//重要:续传必须
Response.AppendHeader("Last-Modified", lastUpdateTiemStr);//把最后修改日期写入响应
Response.ContentType = "application/octet-stream";//MIME类型:匹配任意文件类型
Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);//s HttpUtility.UrlEncode(fileName, Encoding.UTF8).Replace("+", "%20")); Response.AddHeader("Connection", "Keep-Alive");
Response.ContentEncoding = Encoding.UTF8;
if (Request.Headers["Range"] != null)
{//------如果是续传请求,则获取续传的起始位置,即已经下载到客户端的字节数------
Response.StatusCode = ;//重要:续传必须,表示局部范围响应。初始下载时默认为200
string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });//"bytes=1474560-"
startBytes = Convert.ToInt64(range[]);//已经下载的字节数,即本次下载的开始位置
if (startBytes < || startBytes >= fileLength)
{//无效的起始位置
return false;
}
}
Response.AddHeader("Content-Length", (fileLength - startBytes).ToString());
if (startBytes > )
{//------如果是续传请求,告诉客户端本次的开始字节数,总长度,以便客户端将续传数据追加到startBytes位置后----------
Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - , fileLength));
}
#endregion #region -------向客户端发送数据块-------------------
//binaryReader.BaseStream.Seek(startBytes, SeekOrigin.Begin);
int maxCount = (int)Math.Ceiling((fileLength - startBytes + 0.0) / packSize);//分块下载,剩余部分可分成的块数
for (int i = ; i < maxCount && Response.IsClientConnected; i++)
{//客户端中断连接,则暂停
if (fileLength - startBytes < packSize)
packSize = ;
byte[] fdfs = client.download_file(group_name, remote_filename, startBytes, packSize);
Response.BinaryWrite(fdfs);
Response.Flush();
startBytes = startBytes + packSize;
if (sleep > ) Thread.Sleep(sleep);
}
#endregion
}
catch
{
ret = false;
}
finally
{
}
}
catch
{
ret = false;
}
return ret;
}
断点续传方式下载文件效果:

MVC FastDFS断点续传方式上传
文件分段上传至FastDFS首次使用upload_appender_file,之后使用append_file追加。
public string Upload(HttpPostedFileBase file)
{
string group = "";
string path = "";
string tempPath = Server.MapPath("~/File/temp.txt");
byte[] buffer = new byte[file.ContentLength];
System.IO.Stream fs = (System.IO.Stream)file.InputStream;
fs.Read(buffer, , file.ContentLength); NameValuePair[] meta_list = new NameValuePair[];
meta_list[] = new NameValuePair("width", "");
meta_list[] = new NameValuePair("heigth", "");
meta_list[] = new NameValuePair("bgcolor", "#FFFFFF");
meta_list[] = new NameValuePair("author", "Mike");
if (Request.Params["chunk"] == "" || Request.Params["chunk"] == null)
{
string ext = Path.GetExtension(file.FileName).Replace(".", "");
//fastdfs上传
var results = client.upload_appender_file(buffer, ext, meta_list);
group = results[];
path = results[];
//临时存储group、path
StreamWriter sw = new StreamWriter(tempPath, false);
sw.WriteLine(group);
sw.WriteLine(path);
sw.Close(); }
else
{
if (System.IO.File.Exists(tempPath))
{
StreamReader sr = new StreamReader(tempPath);
int i = ;
string strReadline = string.Empty;
//读取group、path
while ((strReadline = sr.ReadLine()) != null)
{
if (i == )
group = strReadline;
else if (i == )
path = strReadline;
i++;
}
sr.Close();
}
//文件续传,fastdfs追加上传
var flag = client.append_file(group, path, buffer);
} return "{\"data\":{\"chunked\" : true, \"ext\" : \"exe\"}}";
} public string GetMaxChunk(string md5)
{
//根据实际存储介质返回文件上传终止的段
return "{\"data\":0}";
}
上传pconline1477535934501.zip文件测试。

上传完成后查看/File/temp.txt文件记录。

到相应的group查看:

WEBAPI FastDFS断点续传方式下载
WEBAPI中PushStreamContent 推送
/// <summary>
/// PushStreamContent 推送
/// FDFS文件,断点续传
/// </summary>
/// <returns></returns>
public HttpResponseMessage GetFileFDFS()
{
HttpResponseMessage response = new HttpResponseMessage();
if (Request.Headers.IfRange != null && Request.Headers.IfRange.EntityTag.ToString().Replace("\"", "") != NowTime)
{
response.StatusCode = HttpStatusCode.PreconditionFailed;
return response;
} string group_name = "group1";
string remote_filename = "M00/00/00/CgEG1FlWChOEHXNFAAAAAEFinIM178.txt";
string fileName = "测试.txt";
long fileLength = ; long speed = * ;
long packSize = * ;
int sleep = (int)Math.Ceiling(1000.0 * packSize / speed);//毫秒数:读取下一数据块的时间间隔
ContentInfo contentInfo = GetContentInfoFromRequest(this.Request, fileLength);
Action<Stream, HttpContent, TransportContext> pushContentAction = (outputStream, content, context) =>
{
try
{
int length = Convert.ToInt32((fileLength - ) - contentInfo.From) + ;
while (length > && packSize > )
{
byte[] fdfs = client.download_file(group_name, remote_filename, contentInfo.From, Math.Min(length, packSize));
outputStream.Write(fdfs, , fdfs.Length);
contentInfo.From = contentInfo.From + fdfs.Length;
length -= fdfs.Length;
if (sleep > ) Thread.Sleep(sleep);
}
//int maxCount = (int)Math.Ceiling((fileLength - contentInfo.From + 0.0) / packSize);//分块下载,剩余部分可分成的块数
//for (int i = 0; i < maxCount && HttpContext.Current.Response.IsClientConnected; i++)
//{
// if (fileLength - contentInfo.From < packSize)
// packSize = 0;
// byte[] fdfs = client.download_file(group_name, remote_filename, contentInfo.From, packSize);
// outputStream.Write(fdfs, 0, fdfs.Length);
// contentInfo.From = contentInfo.From + fdfs.Length;
// if (sleep > 1) Thread.Sleep(sleep);
//}
}
catch (HttpException ex)
{
throw ex;
}
finally
{
outputStream.Close();
}
};
response.Content = new PushStreamContent(pushContentAction, new MediaTypeHeaderValue(MimeType));
//response.Content = new PushStreamContent(pushContentAction);
SetResponseHeaders(response, contentInfo, fileLength, fileName);
return response;
}
demo下载地址:https://pan.baidu.com/s/1i5rDs49
C#集成FastDFS断点续传的更多相关文章
- (转)Spring Boot(十八):使用 Spring Boot 集成 FastDFS
http://www.ityouknow.com/springboot/2018/01/16/spring-boot-fastdfs.html 上篇文章介绍了如何使用 Spring Boot 上传文件 ...
- SpringBoot2.0集成FastDFS
SpringBoot2.0集成FastDFS 前两篇整体上介绍了通过 Nginx 和 FastDFS 的整合来实现文件服务器.但是,在实际开发中对图片或文件的操作都是通过应用程序来完成的,因此,本篇将 ...
- Spring Boot(十八):使用 Spring Boot 集成 FastDFS
上篇文章介绍了如何使用 Spring Boot 上传文件,这篇文章我们介绍如何使用 Spring Boot 将文件上传到分布式文件系统 FastDFS 中. 这个项目会在上一个项目的基础上进行构建. ...
- Spring Boot(十八):使用Spring Boot集成FastDFS
Spring Boot(十八):使用Spring Boot集成FastDFS 环境:Spring Boot最新版本1.5.9.jdk使用1.8.tomcat8.0 功能:使用Spring Boot将文 ...
- spring boot(十八)集成FastDFS文件上传下载
上篇文章介绍了如何使用Spring Boot上传文件,这篇文章我们介绍如何使用Spring Boot将文件上传到分布式文件系统FastDFS中. 这个项目会在上一个项目的基础上进行构建. 1.pom包 ...
- 使用Spring Boot集成FastDFS
原文:http://www.cnblogs.com/ityouknow/p/8298358.html#3893468 上篇文章介绍了如何使用Spring Boot上传文件,这篇文章我们介绍如何使用Sp ...
- SpringBoot集成FastDFS依赖实现文件上传
前言 对FastDFS文件系统安装后的使用. FastDFS的安装请参考这篇:Docker中搭建FastDFS文件系统(多图) 本文环境:IDEA + JDK1.8 + Maven 本文项目代码:ht ...
- spring boot集成FastDFS
官方文档:https://github.com/happyfish100/fastdfs-client-java 一.首先,maven工程添加依赖 <!--fastdfs--> <d ...
- SpringBoot集成FastDFS+Nginx整合基于Token的防盗链
为什么要用SpringBoot? SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人 ...
随机推荐
- Hibernate关联关系配置(一对多,一对一,多对多)
一对多 创建两个类 Manager(一这一端) Worker(多这一端) 即一个经理下有多个员工 package com.hibernate.n21; import java.util.HashS ...
- QT源码查看001-QApplication和QCoreApplication
QCoreApplication和QApplication的区别(1) QApplication这个类是继承QCoreApplication的,而QCoreApplication有继承QObject的 ...
- map 小模板~~~ 写的不好 继续添加
#include<map>#include<string.h>#include<iostream>using namespace std; int main(){ ...
- 7.与python交互
与python交互 在熟练使用sql语句的基础上,开始使用python语言提供的模块与mysql进行交互 这是我们在工作中大事要做的事 先学会sql是基础,一定要熟练编写sql语句 安装引入模块 安装 ...
- [NewCode 6] 重建二叉树
题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- ue4开发入门教程
ue4是一套开源跨平台的游戏引擎,游戏画质3A水准,具有强大的材质编辑器,各种插件齐全.想要学习ue4的,可以参考这篇文章作为入门. 学习这篇文章,建议具有一定的C++基础,对游戏有一定了解. 1.首 ...
- 【转】PowerDesigner快捷键
一般快捷键 快捷键 说明 F4 打开检查模型窗口,检查模型 F5 如果图窗口内的图改变过大小,恢复为原有大小即正常大小 F6 放大图窗口内的图 F7 缩小图窗口内的图 F8 在图窗口内中查看全部图内容 ...
- Codeforces Round #479 (Div. 3)解题报告
题目链接: http://codeforces.com/contest/977 A. Wrong Subtraction 题意 给定一个数x,求n次操作输出.操作规则:10的倍数则除10,否则减1 直 ...
- 试着用java实现DNS(一)——DatagramSocket, DatagramPacket, Message
一般来说,自己编写DNS是没有必要的,目前开源的dns服务软件很多,功能也很强大.但是,有时候又是很有必要的,有着诸多好处.比如说,用于企业内网,简化DNS配置,可以根据企业需求添加新的功能,非常灵活 ...
- Apache VirtualHost的配置
自从电脑更换为mac后, 一直没有时间去配置php的环境.导致每次要更改php代码的时候, 都是本地更改,然后直接推送到服务器上运行 这样的开发和测试及其耗时且繁琐, 所以早上特地决定弄好mac下的p ...