WebApi的檔案上傳功能實現
阿新 • • 發佈:2018-11-22
1.自主宿主HttpSelfHost的實現
#region Web Api監聽 Assembly.Load("Lind.DDD.TestApi"); //手工載入某個api程式集的controller var config = new HttpSelfHostConfiguration("http://localhost:3333"); config.Routes.MapHttpRoute("default", "api/{controller}/{id}", new { id = RouteParameter.Optional }); var server = new HttpSelfHostServer(config); server.OpenAsync().Wait(); Console.WriteLine("Server is opened"); #endregion
也可使用如下方式註冊路由
public class RouteConfig { public static void RegisterRoutes(HttpRouteCollection httpRouteCollection) { httpRouteCollection.MapHttpRoute( //配置路由 "API Default", "api/{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = RouteParameter.Optional }); } }
其中的config可以進行配置
public class HttpSelfHostConfiguration : HttpConfiguration { public HttpSelfHostConfiguration(string baseAddress); public HttpSelfHostConfiguration(Uri baseAddress); public Uri BaseAddress { get; } public HttpClientCredentialType ClientCredentialType { get; set; } public HostNameComparisonMode HostNameComparisonMode { get; set; } public int MaxBufferSize { get; set; } public int MaxConcurrentRequests { get; set; } public long MaxReceivedMessageSize { get; set; } public TimeSpan ReceiveTimeout { get; set; } public TimeSpan SendTimeout { get; set; } public TransferMode TransferMode { get; set; } public System.IdentityModel.Selectors.UserNamePasswordValidator UserNamePasswordValidator { get; set; } public System.IdentityModel.Selectors.X509CertificateValidator X509CertificateValidator { get; set; } protected virtual BindingParameterCollection OnConfigureBinding(HttpBinding httpBinding); }
config.MaxReceivedMessageSize = int.MaxValue;
config.TransferMode = TransferMode.Buffered;
上述兩項配置可以實現不限制檔案大小上傳。
2. 實現上傳功能的WebApi
[HttpPost]
public RestResult Upload()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
try
{
var provider = new MultipartFormDataStreamProvider(PacsEnvironment.PacsTemperature);
var task = Request.Content.ReadAsMultipartAsync(provider);
task.Wait();
foreach (var f in provider.FileData)
{
Logger.ErrorWithFormat("filename:{0}", f.Headers.ContentDisposition.FileName);
Logger.ErrorWithFormat("{0}", f.LocalFileName);
}
return "";
}
catch (System.Exception e)
{
return "";
}
return "";
}
測試工程:
class Program
{
static void Main(string[] args)
{
string fileName = string.Empty;
while (true)
{
Console.Write("input:");
fileName = Console.ReadLine();
if (!File.Exists(fileName))
continue;
WebClient client = new WebClient();
byte[] bytes = client.UploadFile("http://ip:埠/api/Image/UploadAndStoreDicom", fileName);
string str = System.Text.Encoding.UTF8.GetString(bytes);
Console.WriteLine(str);
}
}
}
網上比較完整的用法
public class vUploadController : ApiController
{
public async Task<HttpResponseMessage> Post()
{
//檢查POST的是否為MultiPart
if(!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
//準備CustomMultipart格式的資料流的提供者
//資料將會被載入
string fileSaveLocation = HttpContext.Current.Server.MapPath("~/App_Data");
CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(fileSaveLocation);
List<string> files = new List<string>();
try
{
// Read all contents of multipart message into CustomMultipartFormDataStreamProvider.
await Request.Content.ReadAsMultipartAsync(provider);
foreach (MultipartFileData file in provider.FileData)
{
files.Add(Path.GetFileName(file.LocalFileName));
}
// Send OK Response along with saved file names to the client.
return Request.CreateResponse(HttpStatusCode.OK, files);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
}
// We implement MultipartFormDataStreamProvider to override the filename of File which
// will be stored on server, or else the default name will be of the format like Body-
// Part_{GUID}. In the following implementation we simply get the FileName from
// ContentDisposition Header of the Request Body.
public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public CustomMultipartFormDataStreamProvider(string path) : base(path) { }
public override string GetLocalFileName(HttpContentHeaders headers)
{
return headers.ContentDisposition.FileName.Replace("\"", string.Empty);
}
}
不存檔案到伺服器的方式(雞肋,存了我也可以刪除)
下面的程式碼直接從請求的Content中讀取請求資料,得到MultipartMemoryStreamProvider物件,遍歷該物件的Contents屬性,可以得到包含上傳檔案及form表單資料的HttpContent物件。如何從Contents找到包含檔案資料的HttpContent物件,可以根據HttpContent物件頭部中對應的FileName屬性來判斷,這個需要和前端約定好,檔案資料必須傳入檔名稱。
var multipartMemoryStreamProvider = await Request.Content.ReadAsMultipartAsync();
Dictionary<string, string> dic = new Dictionary<string, string>();
foreach (var content in multipartMemoryStreamProvider.Contents)
{
if (!string.IsNullOrEmpty(content.Headers.ContentDisposition.FileName))
{
using (Stream stream = await content.ReadAsStreamAsync())
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
}
}
else
{
string val = await content.ReadAsStringAsync();
dic.Add(content.Headers.ContentDisposition.Name, val);
}
}