柚子快报激活码778899分享:断点续传(上传)C#版
断点续传(上传)Java版
1. 客户每次上传前先获取一下当前文件已经被服务器接受了多少
2. 上传时设定偏移量
服务端代码如下:
///
/// 断点续传,获取已上传文件大小
///
///
[HttpPost]
public long GetFileLength()
{
long result = 0;
FileStream fStream = null;
BinaryReader bReader = null;
try
{
var fileName = "";
IEnumerable
bool hasFileName = Request.Headers.TryGetValues("FileName", out hasFileNameList);
if (hasFileName && hasFileNameList.Any())
{
fileName = hasFileNameList.First();
}
//设置文件存放路径
string dir = HttpContext.Current.Server.MapPath(@"~\UploadFiles");
fileName= dir+"\\"+fileName;
if (File.Exists(fileName))
{
FileInfo file = new FileInfo(fileName);
result = file.Length;
}
}
catch (Exception ex)
{
logger.Error(ex, ex.Message);
}
return result;
}
///
/// 断点续传 服务端保存文件代码
/// Offset 偏移量
///
///
[HttpPost]
public Bussiness
{
#region Log Test
FileStream fStreamLog = null;
BinaryReader bReaderLog = null;
try
{
fStreamLog = new FileStream(SavePath + "\\" + $"{DateTime.Now:HHmmss}.File.tmp", FileMode.OpenOrCreate, FileAccess.ReadWrite);
int upLoadLengthTest = (int)HttpContext.Current.Request.InputStream.Length;
bReaderLog = new BinaryReader(HttpContext.Current.Request.InputStream);
byte[] dataTest = new byte[upLoadLengthTest];
bReaderLog.Read(dataTest, 0, upLoadLengthTest); //将上传文件流读到byte[]中
fStreamLog.Write(dataTest, 0, upLoadLengthTest); //将byte[]写到文件中,
}
catch (Exception exr)
{
logger.Error(exr, exr.Message);
}
finally
{
if (fStreamLog != null)
{
//释放流
fStreamLog.Close();
}
if (bReaderLog != null)
{
bReaderLog.Close();
}
}
#endregion
var uploadFileName = HttpContext.Current.Request.Form["UploadFileName"];
Bussiness
FileStream fStream = null;
BinaryReader bReader = null;
try
{
long offset = 0; //客户端定义,从X开始往后写,该值由服务端GetFileLength方法提供
IEnumerable
bool hasOffset = Request.Headers.TryGetValues("Offset", out hasOffsetList);
if (hasOffset && hasOffsetList.Any())
{
long.TryParse(hasOffsetList.First(), out offset);
}
var offsetStr = HttpContext.Current.Request.Form["Offset"];
if (!string.IsNullOrEmpty(offsetStr))
{
long.TryParse(offsetStr, out offset);
}
if (string.IsNullOrEmpty(uploadFileName))
{
result.BussinessCode = -1;
result.BussinessMsg = "uploadFileName 上传文件名不能为空";
result.BussinessData = false;
return result;
}
//设置文件存放路径
//string dir = HttpContext.Current.Server.MapPath(SavePath);
string dir = SavePath;
//如果不存在文件夹,就创建文件夹
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
//////var fileName = dir + "\\" + file.FileName; ///TODO
var fileName = dir + "\\" + (string.IsNullOrEmpty(uploadFileName) ? $"{DateTime.Now.ToString("HHmmss")}.txt" : uploadFileName);
fStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
//偏移指针
fStream.Seek(offset, SeekOrigin.Begin);
if (HttpContext.Current.Request.Files.Count > 0)
{
#region 文件形式
HttpPostedFile file = HttpContext.Current.Request.Files["UploadFile"];
int upLoadLength = Convert.ToInt32(file.InputStream.Length);
//从客户端的请求中获取文件流
bReader = new BinaryReader(file.InputStream);
byte[] data = new byte[upLoadLength];
bReader.Read(data, 0, upLoadLength); //将上传文件流读到byte[]中
fStream.Write(data, 0, upLoadLength);//将byte[]写到文件中,
logger.Info($"上传文件 {uploadFileName} Offset => {offset} File.ContentLength => {upLoadLength} => {fileName}");
#endregion
}
else
{
#region Base64
//如果没传文件是以byte[]
var byteFile = HttpContext.Current.Request.Form["UploadFile"];
byte[] byteArray = Convert.FromBase64String(byteFile);
int upLoadLength = Convert.ToInt32(byteArray.Length);
fStream.Write(byteArray, 0, upLoadLength);//将byte[]写到文件中,
logger.Info($"上传文件 {uploadFileName} Offset => {offset} File.ContentLength => {upLoadLength} => {fileName}");
#endregion
}
result.BussinessData = true;
result.BussinessMsg = $"上传成功!";
result.BussinessCode = 0;
}
catch (Exception ex)
{
logger.Error(ex, ex.Message);
result.BussinessCode = -1;
result.BussinessMsg = ex.Message;
result.BussinessData = false;
#region 出异常后,看看客户端上传的啥
FileStream fstreamErr = null;
BinaryReader readerErr = null;
try
{
fstreamErr = new FileStream(SavePath + "\\" + $"{uploadFileName}_{DateTime.Now:HHmmss}.err", FileMode.OpenOrCreate, FileAccess.ReadWrite);
int upLoadLength = (int)HttpContext.Current.Request.InputStream.Length;
readerErr = new BinaryReader(HttpContext.Current.Request.InputStream);
byte[] data = new byte[upLoadLength];
readerErr.Read(data, 0, upLoadLength); //将上传文件流读到byte[]中
fstreamErr.Write(data, 0, upLoadLength); //将byte[]写到文件中,
}
catch (Exception exr)
{
logger.Error(exr, exr.Message);
}
finally
{
if (fstreamErr != null)
{
//释放流
fstreamErr.Close();
}
if (readerErr != null)
{
readerErr.Close();
}
}
#endregion
return result;
}
finally
{
if (fStream != null)
{
//释放流
fStream.Close();
}
if (bReader != null)
{
bReader.Close();
}
}
return result;
}
上传前,源和目标文件对比
用 Postman 测试
先获取已上传文件的大小,供下面设置偏移量使用
上传后的源和目标文件对比
java 客户端代码
package com.vipsoft.demo.Controller;
import org.springframework.core.io.FileSystemResource;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Base64;
@RestController
@RequestMapping("/demo")
public class DemoController {
@GetMapping(value = "/test")
public String login() {
return "这是demo下面的,用来写测试代码,测试通过后,移到正式项目中!";
}
@GetMapping(value = "/uploadFile")
public String uploadFile(HttpServletRequest request) throws Exception {
String url = "http://localhost:44999/api/Upload/UploadFile";
RestTemplate restTemplate = new RestTemplate();
String filePath = "D:\\Projects\\TEST.DAT";
File file = new File(filePath);
FileSystemResource resource = new FileSystemResource(file);
MultiValueMap
param.add("Offset", "6");
param.add("UploadFileName", "ABC.txt");
param.add("UploadFile", resource);
String rev = restTemplate.postForObject(url, param, String.class);
System.out.println(rev);
return rev;
}
@GetMapping(value = "/uploadByte")
public String uploadByte(HttpServletRequest request) throws Exception {
String url = "http://localhost:44999/api/Upload/UploadFile";
RestTemplate restTemplate = new RestTemplate();
String filePath = "D:\\Projects\\TEST.DAT";
File file = new File(filePath);
//每次上传 10KB
int step = 10 * 1024;
for (long i = 0; i <= file.length(); i = i + step) {
//偏移量
long offset = i;
byte[] bytes = new byte[step];
//如果超过了就取最后的。
if (i + step > file.length()) {
bytes = new byte[(int) (file.length() - i)];
}
RandomAccessFile raf = new RandomAccessFile(file, "r");
raf.seek(offset);
int readSize = raf.read(bytes);
MultiValueMap
param.add("Offset", i);
param.add("UploadFileName", "ABC.txt");
//转成 Base64
param.add("UploadFile", Base64.getEncoder().encodeToString(bytes));
String rev = restTemplate.postForObject(url, param, String.class);
//如果接口返回值出错,break
System.out.println(rev);
}
return "";
}
}
C# 客户端伪代码
///
/// 客户端上传伪代码
///
/// 待上传文件全路径
/// 上传时的流量控制,文件较大时,用于切割文件上传
/// 错误信息
///
public static bool UpLoadFile(string fileName, int byteCount, out string msg)
{
msg = "";
bool result = true;
long cruuent = GetServerFileLength(fileName); //客户端需要读取服务器已上传了多少内容,然后从偏移量开始往后读取发送
FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader bReader = new BinaryReader(fStream);
long length = fStream.Length;
fileName = fileName.Substring(fileName.LastIndexOf('\\') + 1);
#region 开始上传文件
try
{
#region 续传处理
byte[] data;
if (cruuent > 0)
{
fStream.Seek(cruuent, SeekOrigin.Current);
}
#endregion
#region 分割文件上传
for (; cruuent <= length; cruuent = cruuent + byteCount)
{
try
{
if (cruuent + byteCount > length)
{
data = new byte[Convert.ToInt64((length - cruuent))];
bReader.Read(data, 0, Convert.ToInt32((length - cruuent)));
}
else
{
data = new byte[byteCount];
bReader.Read(data, 0, byteCount);
}
Hashtable parms = new Hashtable();
parms.Add("Offset", cruuent.ToString());
var falg= PostData("",param);
if (falg == false)
{
break;
}
}
catch (Exception ex)
{
msg = ex.ToString();
result = false;
break;
}
#endregion
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
bReader.Close();
fStream.Close();
}
GC.Collect();
#endregion
return result;
}
柚子快报激活码778899分享:断点续传(上传)C#版
精彩内容
发表评论