ASP.NET如何在Web API中读取多部分表单数据?

时间:2016-11-16 12:19:09

标签: c# asp.net asp.net-web-api

我将多部分表单数据发送到我的Web API,如下所示:

string example = "my string";
HttpContent stringContent = new StringContent(example);
HttpContent fileStreamContent = new StreamContent(stream);
using (var client = new HttpClient())
{
    using (var content = new MultipartFormDataContent())
    {
         content.Add(stringContent, "example", "example");
         content.Add(fileStreamContent, "stream", "stream");
         var uri = "http://localhost:58690/api/method";
         HttpResponseMessage response = await client.PostAsync(uri, content);

这是Web API:

[HttpPost]
[Route("api/method")]
public async Task<HttpResponseMessage> Method()
    {
         // take contents and do something
    }

如何在Web API中读取请求体中的字符串和流?

7 个答案:

答案 0 :(得分:11)

这是我之前用于接收json数据+可选文件的代码:

var result = await Request.Content.ReadAsMultipartAsync();

var requestJson = await result.Contents[0].ReadAsStringAsync();
var request = JsonConvert.DeserializeObject<MyRequestType>(requestJson);

if (result.Contents.Count > 1)
{
    var fileByteArray = await result.Contents[1].ReadAsByteArrayAsync();
    ...
}

您可以在这样的请求中组合不同类型的数据,这非常简洁。

编辑:如何发送此请求的示例:

let serialisedJson = JSON.stringify(anyObject);
let formData = new FormData();
formData.append('initializationData', serialisedJson);
// fileObject is an instance of File
if (fileObject) {
    // the 'jsonFile' name might cause some confusion: 
    // in this case, the uploaded file is actually a textfile containing json data
    formData.append('jsonFile', fileObject);
}

return new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://somewhere.com', true);
    xhr.onload = function(e: any) {
        if (e.target.status === 200) {
            resolve(JSON.parse(e.target.response));
        }
        else {
            reject(JSON.parse(e.target.response));
        }
    };
    xhr.send(formData);
});

答案 1 :(得分:10)

这可以帮助您入门:

 var uploadPath = HostingEnvironment.MapPath("/") + @"/Uploads";
 Directory.CreateDirectory(uploadPath);
 var provider = new MultipartFormDataStreamProvider(uploadPath);
 await Request.Content.ReadAsMultipartAsync(provider);

 // Files
 //
 foreach (MultipartFileData file in provider.FileData)
 {
     Debug.WriteLine(file.Headers.ContentDisposition.FileName);
     Debug.WriteLine("File path: " + file.LocalFileName);
 }

 // Form data
 //
 foreach (var key in provider.FormData.AllKeys)
 {
     foreach (var val in provider.FormData.GetValues(key))
     {
          Debug.WriteLine(string.Format("{0}: {1}", key, val));
     }
 }

答案 2 :(得分:1)

您可以通过这种方式阅读内容并获取所有文件信息(在我的示例图像中),而无需复制到本地磁盘:

public async Task<IHttpActionResult> UploadFile()
{
    if (!Request.Content.IsMimeMultipartContent())
    {
        return StatusCode(HttpStatusCode.UnsupportedMediaType);
    }        

    var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();

    foreach (var stream in filesReadToProvider.Contents)
    {
        // Getting of content as byte[], picture name and picture type
        var fileBytes = await stream.ReadAsByteArrayAsync();
        var pictureName = stream.Headers.ContentDisposition.FileName;
        var contentType = stream.Headers.ContentType.MediaType;
    }
}

答案 3 :(得分:0)

用于发送多个文件

        System.Web.HttpFileCollection hfc = System.Web.HttpContext.Current.Request.Files;

        //// CHECK THE FILE COUNT.
        for (int iCnt = 0; iCnt <= hfc.Count - 1; iCnt++)
        {
            System.Web.HttpPostedFile hpf = hfc[iCnt];
            string Image = UploadDocuments.GetDocumentorfileUri(hpf);
            UploadDocuments.UploadDocumentsIntoData(Image, hpf.FileName, id);

        }

Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME

答案 4 :(得分:0)

 // read the file content without copying to local disk and write the content byte to file 
       try
       {
           var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
           JavaScriptSerializer json_serializer = new JavaScriptSerializer();

           foreach (var stream in filesReadToProvider.Contents)
           {

               //getting of content as byte[], picture name and picture type
               var fileBytes = await stream.ReadAsByteArrayAsync();
               var fileName = stream.Headers.ContentDisposition.Name;

               var pictureName = stream.Headers.ContentDisposition.FileName;
               var contentType = stream.Headers.ContentType.MediaType;
               var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Images/Upload/"), json_serializer.Deserialize<string>(pictureName));

               File.WriteAllBytes(path, fileBytes);
           }

           return Request.CreateResponse(HttpStatusCode.OK);
       }catch(Exception ex)
       {
           return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
       }

答案 5 :(得分:0)

// Web用户界面方法  受保护的无效btnPrescAdd_Click(对象发送者,EventArgs e)         {

UPDATE EDITION
  SET Translations = XMLQUERY('copy $res := $t
                               modify insert node element Translation {attribute Language {"Norwegian"}, attribute Publisher {"KLC"}, attribute Price {200}} 
                               as last into $res/Translations
                               return $res'
                               PASSING Translations AS "t" RETURNING CONTENT)
  where (book, id) in (
    select book, id 
      from (
        select book.id book, edition.id, 
               row_number() over (partition by book.id order by edition.id) rn 
          from book join edition on book.id = edition.book where title = 'Encore une fois')
      where rn = 2);

//请求方法

        NameValueCollection collection = new NameValueCollection();

        collection.Set("c1", Session["CredID"].ToString());
        collection.Set("p1", "");
        collection.Set("p2", Request.Form["ctl00$MainContent$hdnHlthId"]);
        collection.Set("p3", Request.Form["ctl00$MainContent$PresStartDate"]);
        collection.Set("p4", Request.Form["ctl00$MainContent$PrescEndDate"]);

        FileUpload fileUpload = PrescUpload;

        ApiServices<Status> obj = new ApiServices<Status>();
        Status objReturn = obj.FetchObjectUploadAPI("POSTUHRPL", collection, 
         fileUpload, ApiServices<Status>.ControllerType.DU);

    }

https://stackoverflow.com/users/9600164/gaurav-sharma

答案 6 :(得分:0)

聚会太晚了,但其他任何人都必须使用 ASP.NET Web API (1/2):

    [HttpPost, Route("img/up")]
    public async Task<IHttpActionResult> ItemImage()
    {
        var data = HttpContext.Current.Request.Form["example"];
        var item = JsonConvert.DeserializeObject<Example>(data);
        if (item == null) return BadRequest("Invalid request: Example cannot be null");

        var path = HostingEnvironment.MapPath("/") + @"img";
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);

        try
        {
            var image = HttpContext.Current.Request.Files["stream"];
            if (image == null) return BadRequest("Invalid request: no image received.");
            path = $@"{path}\{DateTime.Now:MMddyyHHmmss}.png";
            image.SaveAs(path);
        }
        catch (Exception e)
        {
            // TODO: Document Exception
        }
        return Ok();
    }

在这里您可以看到我们正在接受对 /api/img/up 端点的 HttpPost 请求。 目前我们不检查 Mime 类型,但您可以根据需要进行检查。

首先,我们为您的“示例”获取表单数据并将其从 json 反序列化为 Example 类(将其替换为您用作模型的内容)

然后我们确保 img 目录存在(如果您希望它位于 API 文件之外的某个位置,请修改路径)

然后我们从 stream 获取 HttpContext.Current.Request.Files["stream"] 对象 我从一个端点获取了这个片段,其中文件名是一个时间戳(以支持同一标识符的多个图像)

我尽量保持简单和甜蜜,由于客户端/服务器分层,它可能有点抽象。

如果你需要测试,我推荐PostMan

Sample Postman Test