File upload with Html5 & WebApi &
SignalR (2)
1. Web API with async upload method.
2. Add SignalR
framework to the Web API.
3. Implement the front-end.
[assembly: OwinStartup(typeof(Icash.Tms.Service.Startup))]
namespace Icash.Tms.Service {
public class Startup
{
public void Configuration(IAppBuilder app)
{
try
{
//app.MapSignalR();
app.Map("/SignalR", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors
= true
};
map.RunSignalR(hubConfiguration);
});
}
catch (System.Exception)
{
throw;
}
}
}
}
|
2. We will implement the hub’s method
[HubName("uploaderhub")]
public class UploaderHub : Hub
{
//從其他類別呼叫需用以下方法取得UploaderHub
Instance
static IHubContext HubContext =
GlobalHost.ConnectionManager.GetHubContext<UploaderHub>();
/// <summary>
/// 更新上傳進度 /// </summary> /// <param name="connId">SignalR Connection Id</param> /// <param name="name">FileName</param> /// <param name="message">Message for client</param> public void UpdateProgress( String connId, String name, int percentage, String message) { //Sernd back to certain client with Connection id HubContext.Clients.Client(connId).updateProgress(name, percentage, message) //Send back to all connections //HubContext.Clients.All.updateProgress(name, message); } } |
The updateProgress method will be used in the Front-end to enable the SignalR hub.
3. Modify the upload (POST) method in
Controller, first we must
know the “Connection Id” from the front-end. So we will make
the Connection id as a request parameter from url.
know the “Connection Id” from the front-end. So we will make
the Connection id as a request parameter from url.
private readonly String CENTER_FILE_PATH = @"D:\TEMP\FileCenter";
// POST api/file/Upload [HttpPost, ActionName("Upload")] public async Task<HttpResponseMessage> Post() { try { //Get the POST params NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
var
userId = nvc["user"]
?? String.Empty; //
User Id (optional)
var
typeName = nvc["type"]
?? String.Empty; //sub-folder
(optional)
var
connId = nvc["connId"]
?? String.Empty; //connection
id for SingleR
//Create if necessary this.createCenterDirectory(uploadPath); //Check if the request contains multipart/form-data. if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } //Start Reading multi-part from request var streamProvider = new MultipartFormDataStreamProvider(uploadPath); await Request.Content.ReadAsMultipartAsync(streamProvider); //For each MultipartFileData, save a log and copy it to the local storage
this.handleMultiFileData(
streamProvider,
uploadPath,
typeName, userId, connId);
return Request.CreateResponse(HttpStatusCode.OK); } catch (System.Exception ex) { } } private void handleMultiFileData( MultipartFormDataStreamProvider streamProvider,String uploadPath, String typeName, String userId, String connId) { int current = 1;
int cntFiles = streamProvider.FileData.Count;
foreach (MultipartFileData fileData in streamProvider.FileData) { String fileName = fileData.Headers.ContentDisposition.FileName; if (fileName.StartsWith("\"") && fileName.EndsWith("\"")) { fileName = fileName.Trim('"'); } if (fileName.Contains(@"/") || fileName.Contains(@"\")) { fileName = Path.GetFileName(fileName); } //Send Progress from SignalR hub
this.sendProgressFromHub(connId,
fileName, current, cntFiles);
current++;
//Start writing file-data to storage String tagetFilePath = Path.Combine(uploadPath, fileName); File.Move(fileData.LocalFileName, tagetFilePath); } } /// <summary> /// 送出目前上傳進度給SignalR Hub /// </summary>
/// <param name="connId">Connection id</param>
/// <param name="fileName">檔名</param>
/// <param name="current">current file index</param>
/// <param name="total">total file count</param>
/// <param name="msg">Message</param>
private void sendProgressFromHub(
String connId, String fileName, int current, int total, String msg = "")
{
try { int percentage = (int)System.Math.Round(((double)current / (double)total * 100), 2); String percStr = percentage.ToString() + "%"; if (String.IsNullOrEmpty(msg)) { msg = String.Format("{0:n0}/{1:n0}({2})", current, total, percStr); }
new UploaderHub().UpdateProgress(connId,
fileName, percentage, msg);
}
}
|
4. The webApi with signalR is done! We will
write the Front-end in
the next article.
the next article.
沒有留言:
張貼留言