[英]How to Implement a Web API controller to accept chunked uploads using JQuery File Upload?
正如標題所述,我需要一些幫助來實現Web API控制器以使用JQuery File Upload接受分塊上傳。 任何幫助(包括現有文章/教程的鏈接)將不勝感激。
首先讓我們從客戶端開始。 您必須為分塊上傳設置maxChunkSize選項。 之后,您需要為每個文件指定唯一標識符,以便識別服務器上的每個塊並將相應的塊數據附加到正確的文件中。
$('#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);
}
}
實際上傳文件的服務類。 這支持塊或整個文件。
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
}
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
};
}
}
最后是服務響應模型和塊元數據
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; }
}
你可以在這里找到靈感: 使用HTML5進行拖放和進度條的ASP.NET多文件上傳 。 分塊上傳控制器方法的示例在UploadFile
開始。 在客戶端上,需要根據https://github.com/blueimp/jQuery-File-Upload/wiki/Options設置jquery文件上載選項maxChunkSize
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.