java get方式异步上传文件,用HttpClient 异步 GET 超大文件方法

c#的 下载代码。 还可以扩展更多,看自己需求了。

///

/// Get方式获取文件,支持超大文件

///

/// GET路径

/// get时带入body的数据

/// 缓存尺寸,默认51200

/// 下载中事件

/// Get前

/// 读取流前

/// 设置文件名

/// Get后,销毁response前

/// 异常处理,返回true抛出异常,返回false不抛异常

public async void GetToFile(string url, string data = "", int buffsize = 51200,

Action downloading = null,

Action beforGet = null,

Action beforReadStream = null,

Func setFilePath = null,

Action afterGet = null,

Func onException = null)

{

int intervals = 200; // downloading执行间隔

int readsize = 1; // 每次读取到的尺寸

int totalSize = 0; // 总读取尺寸

int totalReadTimes = 0; // 总读取次数

DateTime downloadStart = DateTime.Now;

#region --默认的downloading委托--

int currReport = 0, reportSize = 5;//这里reportSize实际上以每200次标准读取循环为基数,5就等于 5*200(见intervals)

Action defaultDownloading = (stm, trt, ts) =>

{

currReport++;

if (currReport == reportSize)

{

var tms = (DateTime.Now - stm).TotalSeconds;

var averageVelocity = (ts / Math.Ceiling(tms)) / 1000000;

WriteLine($"TOTAL_SECONDS:{tms} TOTAL_SIZE:{ts} TOTAL_TIMES:{trt} AVERAGE_VELOCITY:{averageVelocity:f2}Mb/S");

currReport = 0;

}

};

if (downloading == null)

{

downloading = defaultDownloading;

}

else // 如果不是空就在委托尾部加上此委托(多播委托)

{

downloading += defaultDownloading;

}

#endregion

#region --默认的设置文件路径方法--

if (setFilePath == null)

{

setFilePath = (resp) =>

{

// 服务端带文件名 就用文件名,不带就用自定义

if (resp.Content.Headers.ContentDisposition.FileName.NullEmpty())

{

return $"datafile.{DateTime.Now.DateTimeID()}.tmp";

}

else

{

return resp.Content.Headers.ContentDisposition.FileName;

}

};

}

#endregion

#region --其他默认--

if(beforReadStream == null)

{

beforReadStream = (resp) => {

WriteLine($"ContentType:{resp.Content.Headers.ContentType},ContentLength:{resp.Content.Headers.ContentLength},FileName:{resp.Content.Headers.ContentDisposition.FileName}");

};

}

if (beforGet == null)

{

beforGet = (q) => { };

}

if(afterGet == null)

{

afterGet = (s) =>

{

var total_seconds = (DateTime.Now - downloadStart).TotalSeconds;

var averageVelocity = (totalSize / Math.Ceiling(total_seconds)) / 1000000;

WriteLine($"TOTAL_SECONDS:{total_seconds} TOTAL_SIZE:{totalSize} TOTAL_TIMES:{totalReadTimes} AVERAGE_VELOCITY:{averageVelocity:f2}Mb/S DOWNLOAD END");

};

}

if(onException == null)

{

onException = (ex) => true;

}

#endregion

using (HttpClient client = new HttpClient())

{

try

{

var uri = MakeFullUri(url);

HttpRequestMessage req = new HttpRequestMessage(new HttpMethod("GET"), uri);

req.Content = new StringContent(data);

beforGet(req);

using (var res = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead).Result)

{

beforReadStream(res);

string filePath = setFilePath(res);

downloadStart = DateTime.Now;

using (Stream contentStream = await res.Content.ReadAsStreamAsync())

using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))

{

byte[] buff = new byte[buffsize];

while (readsize > 0)

{

readsize = contentStream.Read(buff, 0, buffsize);

totalSize += readsize;

//contentStream.Flush();

fs.Write(buff, 0, readsize);

//fs.Flush();

totalReadTimes++;

// 符合间隔数才执行downloading方法

if ((totalReadTimes % intervals) == 0)

{

fs.Flush();

downloading(downloadStart, totalReadTimes, totalSize);

}

}

}

afterGet(res);

}

//return client.GetAsync(uri).Result.Content.ReadAsStringAsync();

}

catch (Exception ex)

{

if (onException(ex))

{

throw ex;

}

}

}

}

python+flask的 下载服务器 代码

from flask import Flask, abort, request, jsonify, Response, send_from_directory, make_response

from flask_cors import CORS

import time

@app.route('/download/', methods=['GET'])

def download(filename):

# 这文件名参数 只是个装饰,没用

data = request.get_data()

print(data)

directory = 'G:\\soft\\Power'

filename = 'XXXXXXXXXXX.1428562995.exe'

response = make_response(send_from_directory(directory, filename, mimetype='application/octet-stream', as_attachment=True))

response.headers["Content-Disposition"] = f"attachment; filename={filename}"# {file_name.encode().decode('utf8')}

return response

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值