隐藏

.NET6 WebApi 大文件上传——分片上传

发布:2022/6/17 9:09:32作者:管理员 来源:本站 浏览次数:2037

本文章向大家介绍.NET6 WebApi 大文件上传——分片上传,主要包括.NET6 WebApi 大文件上传——分片上传使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。



最近遇到大文件上传问题,网上参考后写的小DEMO

WebApi代码


using Microsoft.AspNetCore.Cors;

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.WebUtilities;

using Microsoft.Net.Http.Headers;

using Polly;

using UploadFile.Models;


namespace UploadFile.Controllers

{

[ApiController]

[Route("[controller]/[action]")]

public class UploadController : ControllerBase

{


[EnableCors("AllowSpecificOrigin")]

[HttpPost]

public async Task<IActionResult> RuleUploadFile([FromQuery] SliceFileInfo file)

{

try

{

string path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Upload");


var files = Request.Form.Files;

var buffer = new byte[file.Size];

var fileName = file.Name;

path = path + "//" + fileName + "//";

if (!System.IO.Directory.Exists(path))

{

System.IO.Directory.CreateDirectory(path);

}

string filepath = path + "//" + file.Name + "^" + file.Number;

using (var stream = new FileStream(filepath, FileMode.Append))

{

await files[0].CopyToAsync(stream);

}

var filesList = Directory.GetFiles(Path.GetDirectoryName(path));


//当顺序号等于分片总数量 合并文件

if ((file.Number + 1) == file.Count || filesList.Length == file.Count)

{


await MergeFile(file);

}

return this.Ok();


}

catch (Exception ex)

{

return BadRequest(ex.Message);

}


}

/// <summary>

/// 合并文件

/// </summary>

/// <param name="file"></param>

/// <returns></returns>

private async Task MergeFile(SliceFileInfo file)

{

string path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Upload");

var fileName = file.Name;

path = path + "//" + fileName + "//";

string baseFileName = path + fileName.Split("~")[0].ToString();

if (!System.IO.Directory.Exists(path))

{

System.IO.Directory.CreateDirectory(path);

}

var filesList = Directory.GetFiles(Path.GetDirectoryName(path));

if (filesList.Length != file.Count)

{

return;

}

List<FileSort> lstFile = new List<FileSort>();

foreach (var item in filesList)

{

lstFile.Add(new FileSort()

{

Name = item,

NumBer = Convert.ToInt32(item.Substring(item.IndexOf('^') + 1))

});

}

lstFile = lstFile.OrderBy(x => x.NumBer).ToList();

using (var fileStream = new FileStream(baseFileName, FileMode.Create))

{

//foreach (var fileSort in filesList)

//{

// using (FileStream fileChunk = new FileStream(fileSort, FileMode.Open))

// {

// await fileChunk.CopyToAsync(fileStream);

// }


//}

await Policy.Handle<IOException>()

.RetryForeverAsync()

.ExecuteAsync(async () =>

{

foreach (var fileSort in lstFile)

{

using (FileStream fileChunk = new FileStream(fileSort.Name, FileMode.Open))

{

await fileChunk.CopyToAsync(fileStream);

}


}

});



}

//删除分片文件

foreach (var dirfile in filesList)

{

System.IO.File.Delete(dirfile);

}

}



}

}


Program配置跨域


using Microsoft.AspNetCore.Http.Features;

using Microsoft.AspNetCore.Server.Kestrel.Core;


var builder = WebApplication.CreateBuilder(args);


// Add services to the container.


builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle

builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen();

builder.Services.AddCors(options =>

{

   options.AddPolicy("AllowSpecificOrigin", cors =>

   {

       cors.AllowAnyOrigin();

       cors.AllowAnyHeader();

       //cors.AllowAnyMethod();

   });

});

builder.Services.Configure<FormOptions>(options =>

{

   options.KeyLengthLimit = int.MaxValue;

   options.ValueLengthLimit = int.MaxValue;

   options.MultipartBodyLengthLimit = int.MaxValue;

   options.MultipartHeadersLengthLimit = int.MaxValue;

});

builder.Services.Configure<KestrelServerOptions>(options =>

{

   options.Limits.MaxRequestBodySize = int.MaxValue;

   options.Limits.MaxRequestBufferSize = int.MaxValue;

});

var app = builder.Build();


// Configure the HTTP request pipeline.

if (app.Environment.IsDevelopment())

{

   app.UseSwagger();

   app.UseSwaggerUI();

}

app.UseCors("AllowSpecificOrigin");

app.UseAuthorization();


app.MapControllers();


app.Run();


前台VUE


<!DOCTYPE html>

<html>

<head>

   <meta charset="utf-8" />

   <title></title>

   <script src="https://unpkg.com/vue@3.2.31/dist/vue.global.js"></script>

   <script src="https://unpkg.com/axios@0.26.1/dist/axios.min.js"></script>

</head>

<body>

   <div id="app">

       <input type="file" id="fileExport" @change="handleFileChange" ref="inputer">

       <button @click="loadfile">开始上传</button>

       <button @click="load">分片上传</button>

   </div>

   <script>

       var obj = {

           data() {

               return {

                   Title: "上传文件",

                   file: {},

               };

           },

           methods: {

               handleFileChange(e) {

                   let inputDOM = this.$refs.inputer;

                   this.file = inputDOM.files[0];// 通过DOM取文件数据


               },

               loadfile() {

                   let size = Math.floor(this.file.size / 1024);//计算文件的大小

                   let formData = new FormData();//new一个formData事件

                   formData.append("files", this.file); //将file属性添加到formData里

                   debugger;

                   fetch("http://localhost:5128/Upload/RuleUploadFile", {

                       method: 'post',

                       body: formData,

                       headers: {

                           /*"Content-Type": "multipart/form-data;",*/

                       }

                   }).then(r => r.json()).then(r => {

                       console.log(r);

                   }).catch(e => {

                       console.log(e);

                   })

               },

               S4() {

                   return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);

               },


               guid() {

                   return (this.S4() + this.S4() + "-" + this.S4() + "-" + this.S4() + "-" + this.S4() + "-" + this.S4() + this.S4() + this.S4());

               },

               load() {

                   let size = this.file.size;//文件大小


                   let maxZrea = 8;              //设置每个分区大小 MB

                   let bufferSize = maxZrea * (1024 * 1024);

                   let fileStart = 0;

                   let fileEnd = bufferSize;

                   let arrFile = [];

                   while (fileStart < size) {

                       var fileInfo = {

                           File: this.file.slice(fileStart, fileEnd),

                           Start: fileStart,

                           End: fileEnd

                       }

                       arrFile.push(fileInfo);

                       fileStart = fileEnd;

                       fileEnd = fileStart + bufferSize;

                   }

                   let count = arrFile.length;

                   let filename = this.file.name + "~" + this.guid();

                   for (var i = 0; i < count; i++) {

                       let formData = new FormData();//new一个formData事件

                       formData.append("file", arrFile[i].File); //将file属性添加到formData里

                       var url = "http://localhost:5128/Upload/RuleUploadFile?Name=" + filename + "&Number=" + i + "&BufferSize=" + bufferSize + "&Count=" + count + "&Start=" + arrFile[i].Start + "&End=" + arrFile[i].End + "&Size=" + size;

                       /*var url = "http://192.168.0.166:8080/Upload/RuleUploadFile?Name=" + filename + "&Number=" + i + "&BufferSize=" + bufferSize + "&Count=" + count + "&Start=" + arrFile[i].Start + "&End=" + arrFile[i].End + "&Size=" + size;*/

                       //fetch(url, {

                       //    method: 'post',

                       //    body: formData,

                       //    headers: {

                       //        /*"Content-Type": "multipart/form-data;",*/

                       //    }

                       //}).then(r => r.json()).then(r => {

                       //    console.log(r);

                       //}).catch(e => {

                       //    console.log(e);

                       //})

                       axios.post(url, formData, {

                           headers: {

                               "Content-Type": "multipart/form-data;",

                           }

                       }).then(r => {

                           console.log(r);

                       }).catch(e => {

                           console.log(e);

                       });

                   }

               }

           }

       };

       var vm = Vue.createApp(obj).mount("#app");

   </script>

</body>

</html>


实测1G文件本地开发环境上传速度在20秒左右,网络环境没有测试过


原文地址:https://www.cnblogs.com/lyzi/p/16008776.html