将图像发布到 asp.net API 2 和 angular 2

Posted

技术标签:

【中文标题】将图像发布到 asp.net API 2 和 angular 2【英文标题】:post image to asp.net API 2 and angular 2 【发布时间】:2016-11-27 00:12:56 【问题描述】:

当我尝试将图像发布到 ASP.Net API 2 时,我得到 415(不支持的媒体类型) 此资源不支持请求实体的媒体类型“multipart/form-data”。","exceptionMessage": "没有 MediaTypeFormatter 可用于从媒体类型为“multipart/form-data”的内容中读取“附件”类型的对象.

我的后端发布方法:

    [HttpPost]
    [Route("api/listing/listingId/Attachment/")]
    public async Task<dynamic> Post([FromBody] Attachment model)
    

        var Attachments = new Attachment
        

            ListingId = model.ListingId,
            Content = model.Content,
            Description = model.Description,
            Name = model.Name,
            MimeType = model.MimeType,
            Size = model.Size,
            CreatedOn = DateTime.UtcNow,
            UpdatedOn = model.UpdatedOn,
        ;

        return await DataStore.InsertDynamicAsync(Attachments);
     

我的前端方法:

  onChangeImage(e: any) 
      console.log(this.className + 'onChangeImage.event=' +JSON.stringify(event));
console.log(this.className + 'onChangeImage._listingAttachmentService undefined?: ' + (this._listingAttachmentService === undefined));
const inputElement = this.fileInput.nativeElement;

const fileList = inputElement.files;
const files = [];
console.log('AttachmentsTabComponent: file count = ' + fileList.length);

if (fileList.length > 0) 

  for (let i = 0; i < fileList.length; i++) 

    // get item
    const file = fileList.item(i);
    files.push(file);
    const model: Attachment = 
      listingId: this.listing.id,

      mimeType: file.type,
      name: file.name,
      size: file.size,
      updatedOn: file.lastModifiedDate
    ;



    const reader = new FileReader();
    reader.readAsDataURL(file);

    console.log(this.className + 'onChangeImage.listingAttachmentService (before reader.onload) undefined?: ' + (this._listingAttachmentService === undefined));

    reader.onload = (readerEvt: any) => 
      const binaryString = readerEvt.target.result;

      //base-64 encoded ASCII string
      model.content = btoa(binaryString);

      console.log(this.className + 'onChangeImage.listingAttachmentService (during reader.onload) undefined?: ' + (this._listingAttachmentService === undefined));

      console.log(this.className + 'ListingAttachmentModel.content.length=' + JSON.stringify(model.content.length));
      // this._listingAttachmentService.add(model);
    ;
  

  // try to clear the file input
  try 
    // TODO: fix this
    this.fileForm.nativeElement.reset();
    inputElement.value = '';
    if (inputElement.value) 
      inputElement.type = 'text';
      inputElement.type = 'file';
    
   catch (e)  

  this._listingAttachmentService.upload(this.listing.id, files)
    .subscribe(data => 
      this.listing.attachments = data;
    );

    

还有我的listingAttachmentService

upload(listingId: number, files: Array<File>) 

this._logger.debug('method upload() entered');
this._logger.debug('upload() listingId=' + listingId);
this._logger.debug('this.fileToUpload.length=' + files.length);

var self = this;

return Observable.create(observer => 
  console.log('creating Observable');
  let formData: FormData = new FormData(),
    xhr: XMLHttpRequest = new XMLHttpRequest();

  formData.append('listingId', listingId);
  for (let i = 0; i < files.length; i++) 
    formData.append('uploads[]', files[i], files[i].name);
  

  xhr.onreadystatechange = () => 
    if (xhr.readyState === 4) 
      if (xhr.status === 200) 
        observer.next(JSON.parse(xhr.response));
        observer.complete();
       else 
        observer.error(xhr.response);
      
    
  ;

  let newbaseUrl = self.baseUrl + listingId + '/attachment/' ;
  xhr.open('POST', newbaseUrl, true);
  xhr.send(formData);
)
  .catch(this.handleError);

【问题讨论】:

你能检查我的答案吗? 【参考方案1】:

您应该使用自定义 MediaTypeFormatter。更多信息在这里:http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters 和示例在这里http://blog.marcinbudny.com/2014/02/sending-binary-data-along-with-rest-api.html#.V5MDDzV7qYg

    public class CustomFormatter : MediaTypeFormatter
    
        public CustomFormatter()
        
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));
        

        public override bool CanReadType(Type type)
        
            return type == typeof(Attachment);
        

        public override bool CanWriteType(Type type)
        
            return false;
        

        public async override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
        
            var provider = await content.ReadAsMultipartAsync();

            var modelContent = provider.Contents
                .FirstOrDefault(c => c.Headers.ContentType.MediaType == "application/json"); // Can also use ContentDisposition.Name.Normalize == "attachment"

            var attachment = await modelContent.ReadAsAsync<Attachment>();

            var fileContents = provider.Contents
                .Where(c => c.Headers.ContentType.MediaType == "image/jpeg").FirstOrDefault(); // can also use ContentDisposition.Name.Normalize() == "image"

            attachment.Content = await fileContents.ReadAsByteArrayAsync();

            return attachment;

        
    

注册自定义媒体格式化程序:

private void ConfigureWebApi(HttpConfiguration config)

    //other code here
    config.Formatters.Add(new CustomFormatter());
   

一个帖子会喜欢下面

POST http://localhost/api/FileUpload HTTP/1.1
Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468
User-Agent: Fiddler
Content-Length: 88778

---------------------------acebdf13572468
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=attachment

"ListingId":"testl"
---------------------------acebdf13572468
Content-Disposition: form-data; name=image; filename=image.jpg
Content-Type: image/jpeg

Image content
---------------------------acebdf13572468--

希望这会有所帮助。

【讨论】:

我检查了你的答案,但我收到 500 个内部服务器错误并显示错误消息 发生错误。", "exceptionMessage": "对象引用未设置为对象的实例 "stackTrace": " at OutdoorAccess.Api.Utilities.CustomFormatter.c.b__3_0(HttpContent c) in C:\\Users\\keroles.hakem\\Documents\\ mvp\\web-api\\OutdoorAccess.Api\\Utilities\\CustomFormatter.cs:line 36\r\n at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1 source, Func2 谓词)\r\n at OutdoorAccess.Api.Utilities.CustomFormatter.d__3.MoveNext() 在 C:\\Users\\keroles.hakem\\Documents\\mvp\\web-api\\OutdoorAccess.Api\\Utilities\\CustomFormatter。 cs:line 35\r\n--- 堆栈跟踪结束... 看起来您的帖子没有 content-type:image/jpeg 。您上传的图片的内容类型是什么?您能否在此处跟踪您的帖子并更新。 我正在使用 Observable 查看 onChangeImage() 方法并在我的问题中上传。 你能在xhr.send(formData);前面加上xhr.setRequestHeader("Content-type", "image/jpeg");

以上是关于将图像发布到 asp.net API 2 和 angular 2的主要内容,如果未能解决你的问题,请参考以下文章

是否有推荐的方法来使用 ASP.NET Web API 返回图像

如何将 multipart/form-data 发送到 ASP.NET Core Web API?

亚马逊 API ASP.NET

如何将 AzureAD 和 AzureADBearer 添加到 asp.net core 2.2 web api

在 ASP.NET Core Web API 中上传文件和 JSON

将 JWT 身份验证实现从 .net core 2 转移到 asp.net web api 2