gpt4 book ai didi

c# - 如何实现 Web API Controller 以使用 JQuery 文件上传接受分块上传?

转载 作者:太空狗 更新时间:2023-10-29 18:14:52 28 4
gpt4 key购买 nike

如标题所述,我需要一些帮助来实现 Web API Controller 以接受使用 JQuery 文件上传的分块上传。非常感谢任何帮助(包括现有文章/教程的链接)。

最佳答案

首先让我们从客户端开始。您必须为分块上传设置 maxChunkSize 选项。之后,每个文件都需要一个唯一标识符,以便识别服务器上的每个 block 并将相应的 block 数据附加到正确的文件。

$('#fileupload')
.bind('fileuploadsubmit', function (e, data) {
data.headers = $.extend(data.headers,
{"X-File-Identifier": generateFileUniqueIdentifier(data)})
});
});

generateFileUniqueIdentifier = function(data){
var file=data.files[0],
var result = file.relativePath||file.webkitRelativePath||file.fileName||file.name;

return result.replace(/[^0-9a-zA-Z_-]/img,"") + "-" + i.size + "-" + $.now()
}

现在在服务器端:ApiController

 public class UploadController : ApiController
{
[HttpPost]
[Route("upload/{targetFolder:int}")]
[ValidateMimeMultipartContentFilter]
public async Task<IHttpActionResult> UploadDocument(int targetFolder)
{
var uploadFileService = new UploadFileService();
UploadProcessingResult uploadResult = await uploadFileService.HandleRequest(Request);

if (uploadResult.IsComplete)
{
// do other stuff here after file upload complete
return Ok();
}

return Ok(HttpStatusCode.Continue);

}
}

实际上传文件的服务类。这支持 block 或整个文件。

public class UploadFileService
{
private readonly string _uploadPath;
private readonly MultipartFormDataStreamProvider _streamProvider;

public UploadFileService()
{
_uploadPath = UserLocalPath;
_streamProvider = new MultipartFormDataStreamProvider(_uploadPath);
}

#region Interface

public async Task<UploadProcessingResult> HandleRequest(HttpRequestMessage request)
{
await request.Content.ReadAsMultipartAsync(_streamProvider);
return await ProcessFile(request);
}

#endregion

#region Private implementation

private async Task<UploadProcessingResult> ProcessFile(HttpRequestMessage request)
{
if (request.IsChunkUpload())
{
return await ProcessChunk(request);
}

return new UploadProcessingResult()
{
IsComplete = true,
FileName = OriginalFileName,
LocalFilePath = LocalFileName,
FileMetadata = _streamProvider.FormData
};
}

private async Task<UploadProcessingResult> ProcessChunk(HttpRequestMessage request)
{
//use the unique identifier sent from client to identify the file
FileChunkMetaData chunkMetaData = request.GetChunkMetaData();
string filePath = Path.Combine(_uploadPath, string.Format("{0}.temp", chunkMetaData.ChunkIdentifier));

//append chunks to construct original file
using (FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate | FileMode.Append))
{
var localFileInfo = new FileInfo(LocalFileName);
var localFileStream = localFileInfo.OpenRead();

await localFileStream.CopyToAsync(fileStream);
await fileStream.FlushAsync();

fileStream.Close();
localFileStream.Close();

//delete chunk
localFileInfo.Delete();
}

return new UploadProcessingResult()
{
IsComplete = chunkMetaData.IsLastChunk,
FileName = OriginalFileName,
LocalFilePath = chunkMetaData.IsLastChunk ? filePath : null,
FileMetadata = _streamProvider.FormData
};

}

#endregion

#region Properties

private string LocalFileName
{
get
{
MultipartFileData fileData = _streamProvider.FileData.FirstOrDefault();
return fileData.LocalFileName;
}
}

private string OriginalFileName
{
get
{
MultipartFileData fileData = _streamProvider.FileData.FirstOrDefault();
return fileData.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
}
}

private string UserLocalPath
{
get
{
//return the path where you want to upload the file
}
}

#endregion
}

用于识别 block 请求的 HttpRequestMessagge 扩展

public static class HttpRequestMessageExtensions
{
public static bool IsChunkUpload(this HttpRequestMessage request)
{
return request.Content.Headers.ContentRange != null;
}

public static FileChunkMetaData GetChunkMetaData(this HttpRequestMessage request)
{
return new FileChunkMetaData()
{
ChunkIdentifier = request.Headers.Contains("X-DS-Identifier") ? request.Headers.GetValues("X-File-Identifier").FirstOrDefault() : null,
ChunkStart = request.Content.Headers.ContentRange.From,
ChunkEnd = request.Content.Headers.ContentRange.To,
TotalLength = request.Content.Headers.ContentRange.Length
};
}
}

最后是服务响应模型和 block 元数据

public class FileChunkMetaData
{
public string ChunkIdentifier { get; set; }

public long? ChunkStart { get; set; }

public long? ChunkEnd { get; set; }

public long? TotalLength { get; set; }

public bool IsLastChunk
{
get { return ChunkEnd + 1 >= TotalLength; }
}
}

public class UploadProcessingResult
{
public bool IsComplete { get; set; }

public string FileName { get; set; }

public string LocalFilePath { get; set; }

public NameValueCollection FileMetadata { get; set; }
}

MultiPartContentFilter 只是一个用于验证内容的 ActionFilter (from damienbod)

public class ValidateMimeMultipartContentFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
}

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{

}

}

关于c# - 如何实现 Web API Controller 以使用 JQuery 文件上传接受分块上传?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26546296/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com