ファイルをアップロードし、ファイルとともに追加情報を送信します。たとえば、文字列fooとint barを送信します。
ファイルアップロード、文字列、およびintを受け取るASP.NET WebAPIコントローラーメソッドをどのように記述しますか?
私のJavaScript:
var fileInput = document.querySelector("#filePicker");
var formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("foo", "hello world!");
formData.append("bar", 42);
var options = {
url: "/api/foo/upload",
data: formData,
processData: false // Prevents JQuery from transforming the data into a query string
};
$.ajax(options);
私のWebAPIコントローラーは、次のようにファイルにアクセスできます。
public async Task<HttpResponseMessage> Upload()
{
var streamProvider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(streamProvider);
var fileStream = await streamProvider.Contents[0].ReadAsStreamAsync();
}
しかし、文字列とintをどのように取得できるかは明確ではありません。おそらくstreamProvider.Content [1]などと言うことができると思いますが、それは非常に厄介です。
ファイルのアップロード、文字列、およびintを受け入れるWebAPIアクションを記述する正しい方法©とは何ですか?
独自のMultipartFileStreamProvider
を作成して、追加の引数にアクセスできます。
ExecutePostProcessingAsync
では、各ファイルをマルチパート形式でループし、カスタムデータをロードします(ファイルが1つしかない場合は、CustomData
リストにオブジェクトが1つだけあります)。
class MyCustomData
{
public int Foo { get; set; }
public string Bar { get; set; }
}
class CustomMultipartFileStreamProvider : MultipartMemoryStreamProvider
{
public List<MyCustomData> CustomData { get; set; }
public CustomMultipartFileStreamProvider()
{
CustomData = new List<MyCustomData>();
}
public override Task ExecutePostProcessingAsync()
{
foreach (var file in Contents)
{
var parameters = file.Headers.ContentDisposition.Parameters;
var data = new MyCustomData
{
Foo = int.Parse(GetNameHeaderValue(parameters, "Foo")),
Bar = GetNameHeaderValue(parameters, "Bar"),
};
CustomData.Add(data);
}
return base.ExecutePostProcessingAsync();
}
private static string GetNameHeaderValue(ICollection<NameValueHeaderValue> headerValues, string name)
{
var nameValueHeader = headerValues.FirstOrDefault(
x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
return nameValueHeader != null ? nameValueHeader.Value : null;
}
}
次に、コントローラーで:
class UploadController : ApiController
{
public async Task<HttpResponseMessage> Upload()
{
var streamProvider = new CustomMultipartFileStreamProvider();
await Request.Content.ReadAsMultipartAsync(streamProvider);
var fileStream = await streamProvider.Contents[0].ReadAsStreamAsync();
var customData = streamProvider.CustomData;
return Request.CreateResponse(HttpStatusCode.Created);
}
}
ここでの答えは素晴らしいと思います。そのため、要約形式のファイルに加えてデータを渡す方法のやや単純な例を見ることができます。FileUploadコントローラーへのWebAPI呼び出しを行うJavascript関数、およびFileUploadコントローラーからのスニペット(VB.net)が含まれますJavaScriptから渡された追加データを読み取ります。
Javascript:
function uploadImage(files) {
var data = new FormData();
if (files.length > 0) {
data.append("UploadedImage", files[0]);
data.append("Source", "1")
var ajaxRequest = $.ajax({
type: "POST",
url: "/api/fileupload/uploadfile",
contentType: false,
processData: false,
data: data
});
ファイルアップロードコントローラー:
<HttpPost> _
Public Function UploadFile() As KeyValuePair(Of Boolean, String)
Try
If HttpContext.Current.Request.Files.AllKeys.Any() Then
Dim httpPostedFile = HttpContext.Current.Request.Files("UploadedImage")
Dim source = HttpContext.Current.Request.Form("Source").ToString()
Javascriptでわかるように、渡される追加データは「ソース」キーで、値は「1」です。そして、Chandrikaが上記で回答したように、コントローラーはこの渡されたデータを「System.Web.HttpContext.Current.Request.Form( "Source")。ToString()」を通して読み取ります。
コントローラコードはVB.netにあるため、Form( "Source")は()(vs. [])を使用することに注意してください。
お役に立てれば。
この方法で、複数のファイルと複数の属性を抽出できます。
public async Task<HttpResponseMessage> Post()
{
Dictionary<string,string> attributes = new Dictionary<string, string>();
Dictionary<string, byte[]> files = new Dictionary<string, byte[]>();
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.Contents)
{
if (file.Headers.ContentDisposition.FileName != null)
{
var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
var buffer = await file.ReadAsByteArrayAsync();
files.Add(filename, buffer);
} else
{
foreach(NameValueHeaderValue p in file.Headers.ContentDisposition.Parameters)
{
string name = p.Value;
if (name.StartsWith("\"") && name.EndsWith("\"")) name = name.Substring(1, name.Length - 2);
string value = await file.ReadAsStringAsync();
attributes.Add(name, value);
}
}
}
//Your code here
return new HttpResponseMessage(HttpStatusCode.OK);
}
次の方法でそれを行うことができます:JQueryメソッド:
var data = new FormData();
data.append("file", filesToUpload[0].rawFile);
var doc = {};
doc.DocumentId = 0;
$.support.cors = true;
$.ajax({
url: '/api/document/uploaddocument',
type: 'POST',
contentType: 'multipart/form-data',
data: data,
cache: false,
contentType: false,
processData: false,
success: function (response) {
docId = response.split('|')[0];
doc.DocumentId = docId;
$.post('/api/document/metadata', doc)
.done(function (response) {
});
alert('Document save successfully!');
},
error: function (e) {
alert(e);
}
});
'UploadDocuement' Web APIを呼び出します
[Route("api/document/uploaddocument"), HttpPost]
[UnhandledExceptionFilter]
[ActionName("UploadDocument")]
public Task<HttpResponseMessage> UploadDocument()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
Task<HttpResponseMessage> mytask = new Task<HttpResponseMessage>(delegate()
{
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest,
Content = "In valid file & request content type!".ToStringContent()
};
});
return mytask;
}
string root = HttpContext.Current.Server.MapPath("~/Documents");
if (System.IO.Directory.Exists(root))
{
System.IO.Directory.CreateDirectory(root);
}
var provider = new MultipartFormDataStreamProvider(root);
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
if (o.IsFaulted || o.IsCanceled)
throw new HttpResponseException(HttpStatusCode.InternalServerError);
FileInfo finfo = new FileInfo(provider.FileData.First().LocalFileName);
string guid = Guid.NewGuid().ToString();
File.Move(finfo.FullName, Path.Combine(root, guid + "_" + provider.FileData.First().Headers.ContentDisposition.FileName.Replace("\"", "")));
string sFileName = provider.FileData.First().Headers.ContentDisposition.FileName.Replace("\"", "");
FileInfo FInfos = new FileInfo(Path.Combine(root, guid + "_" + provider.FileData.First().Headers.ContentDisposition.FileName.Replace("\"", "")));
Document dbDoc = new Document()
{
DocumentID = 0
};
context.DocumentRepository.Insert(dbDoc);
context.Save();
return new HttpResponseMessage()
{
Content = new StringContent(string.Format("{0}|File uploaded.", dbDoc.DocumentID))
};
}
);
return task;
}
次の方法でメタデータWeb APIを呼び出します。
[Route("api/document/metadata"), HttpPost]
[ActionName("Metadata")]
public Task<HttpResponseMessage> Metadata(Document doc)
{
int DocId = Convert.ToInt32(System.Web.HttpContext.Current.Request.Form["DocumentId"].ToString());
Task<HttpResponseMessage> mytask = new Task<HttpResponseMessage>(delegate()
{
return new HttpResponseMessage()
{
Content = new StringContent("metadata updated")
};
});
return mytask;
}