我使用ASP.NET WEBAPI在代码下面创建了一个文件上传方法:
[DataContract]
public class FileDesc
{
[DataMember]
public string name { get; set; }
[DataMember]
public string url { get; set; }
[DataMember]
public long size { get; set; }
[DataMember]
public string UniqueFileName { get; set; }
[DataMember]
public int id { get; set; }
[DataMember]
public DateTime modifiedon { get; set; }
[DataMember]
public string description { get; set; }
public FileDesc(string rootUrl, FileInfo f,int pId, string aFileName)
{
id = pId;
name = aFileName;
UniqueFileName = f.Name;
url = rootUrl + "/Files/" + f.Name;
size = f.Length / 1024;
modifiedon = f.LastWriteTime;
description = aFileName;
}
}
public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
//string uniqueFileName = string.Empty;
public string UniqueFileName
{
get;
set;
}
public string ActualFileName
{
get;
set;
}
public int TaskID { get; set; }
private int UserID { get; set; }
public CustomMultipartFormDataStreamProvider(string path, int ptaskID, int pUserID)
: base(path)
{
TaskID = ptaskID;
UserID = pUserID;
}
public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
{
var name = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? headers.ContentDisposition.FileName : "NoName";
ActualFileName = name.Replace("\"", string.Empty);
ActualFileName = Path.GetFileName(ActualFileName);
UniqueFileName = Guid.NewGuid().ToString() + Path.GetExtension(ActualFileName);
int id = SaveFileInfoIntoDatabase(ActualFileName, TaskID, UniqueFileName, UserID);
headers.Add("ActualFileName", ActualFileName);
headers.Add("id", id.ToString());
return UniqueFileName;
}
}
[Authorize]
public class FileUploadController : ApiController
{
private string StorageRoot
{
get { return Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/Files/")); } //Path should! always end with '/'
}
public Task<IEnumerable<FileDesc>> Post(int id)
{
string folderName = "Files";
string PATH = HttpContext.Current.Server.MapPath("~/" + folderName);
string rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
HttpContext.Current.Response.BufferOutput = true;
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.ContentType = "text/html";
if (Request.Content.IsMimeMultipartContent())
{
var streamProvider = new CustomMultipartFormDataStreamProvider(PATH, id, BEL_PMS.Utilities.FormsAuthenticationUtil.GetCurrentUserID);
var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<IEnumerable<FileDesc>>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
var fileInfo = streamProvider.FileData.Select(i =>
{
var info = new FileInfo(i.LocalFileName);
int FileID = Convert.ToInt32((from h in i.Headers where h.Key =="id" select h.Value.First()).FirstOrDefault());
string ActualFileName = (from h in i.Headers where h.Key =="ActualFileName" select h.Value.First()).FirstOrDefault();
return new FileDesc(rootUrl, info, FileID, ActualFileName);
});
return fileInfo;
});
//return new HttpResponseMessage { StatusCode = System.Net.HttpStatusCode.OK, Content = task};
return task;
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
}
}
}
使用jquery.form.js插件通过Ajax上传文件,下面是代码:
$('#frmmultiupload').ajaxForm({
success: OnUploadedSuccessfully,
error: function (x, y) {
mesg('Error occured while file upload! Please make sure that total file size is less than 4 MB and try again.',
'error', 'File upload failed.');
}
});
一切工作文件,但它在IE9中创建问题
IE说“您想要从本地主机打开还是保存?”
以下是网络跟踪:
我发现了一些提示here并不知道如何将Task<IEnumerable<FileDesc>>
转换为Task<HttpResponseMessage>
。
我在ajaxSetup中指定了超时30秒,所以在30秒后它会产生错误。
答案 0 :(得分:4)
var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
var fileInfo = streamProvider.FileData.Select(i =>
{
var info = new FileInfo(i.LocalFileName);
int FileID = Convert.ToInt32((from h in i.Headers where h.Key =="id" select h.Value.First()).FirstOrDefault());
string ActualFileName = (from h in i.Headers where h.Key =="ActualFileName" select h.Value.First()).FirstOrDefault();
return new FileDesc(rootUrl, info, FileID, ActualFileName);
});
var response = Request.CreateResponse(HttpStatusCode.OK, fileInfo);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
return response;
});
答案 1 :(得分:3)
IE 9不支持新的XMLHttpRequest Level 2(仅限IE10 +),这意味着jquery.form.js插件使用iframe回退。 阅读:jquery.form.js插件的创建者发布的http://www.malsup.com/jquery/form/#file-upload。他声称,如果返回数据是JSON或Script,IE将提示下载。如果你返回JSON,你必须强制内容类型标题为“text / html”。
答案 2 :(得分:1)
我也经历过同样的问题,这个问题只会在IE提交表单时发生,而且它引用的WebApi函数会返回一些值。我们还没有一个理想的解决方案来解决这个问题。
在我们的例子中,我们所做的是将函数拆分为两个调用。第一个函数将保存数据库中的详细信息(假设上传成功),并且在回调时我们将提交表单以上传文件。 webapi上传功能的返回类型为void
。如果上传失败,我们将在错误回调中处理,然后从数据库中删除相应的条目。
我知道这根本不是一个好的解决方法,但我们已经接受了它。
同时检查此question。