0

我编写了一些代码 (MetadataProcessor) 来定位 xml 文件并将其发送到 API ( http://localhost:5000/api/Events/UploadAzureEncodedMetadata ) 以进行解析。但是,调用 API 时,IFormFile 参数始终为空。我已经用 fiddler 检查了生成的 http 请求,以确定是什么导致了模型绑定问题(如果是这样的话),但我没有发现任何问题。

元数据处理器:

 // Build a path to the directory containing the metadata file
            string folderName = string.Format("OUTPUT_ENCODER_{0}_{1}", eventId, id);
            string folderPath = Path.Combine(
                this._config.MediaBasePath,
                clientId.ToString(),
                eventId.ToString(),
                "results",
                folderName);

            // Find the metadata file
            string fileName = null;
            byte[] data = null;
            bool exists = false;
            string[] files = Directory.GetFiles(folderPath);

            foreach (var file in files)
            {
                if (file.EndsWith("_metadata.xml"))
                {
                    data = File.ReadAllBytes(file);
                    exists = true;
                    fileName = file;
                    break;
                }
            }

            // Generate token for access to Events controller
            TokenProvider tokens = new TokenProvider(this._config, this._logger);
            var authValue = new AuthenticationHeaderValue("Bearer", tokens.GetTokenObject(clientId));


            // Build the HttpClient
            HttpClient client = new HttpClient()
            {
                DefaultRequestHeaders =
                                            {
                                                Authorization = authValue
                                            }
            };

            // Bundle the xml data into the request body
            ByteArrayContent formFile = new ByteArrayContent(data, 0, data.Length);

            MultipartFormDataContent multiContent = new MultipartFormDataContent();
            multiContent.Add(formFile, "formFile", fileName);

            // Post to EventsController
            var baseUri = new Uri(this._config.BaseUrl);

            var url = new Uri(baseUri, string.Format("{0}api/Events/UploadAzureEncodedMetadata/{1}", baseUri, videoId));
            var result = await client.PostAsync(url.ToString(), multiContent);

API 中的 MVC 控制器:

[HttpPost("UploadAzureEncodedMetadata/{id}")]
        [ProducesResponseType(201)]
        [ProducesResponseType(400)]
        [ProducesResponseType(401)]
        [ProducesResponseType(404)]
        public async Task<IActionResult> UpdateDuration([FromRoute]Guid id, [FromForm]IFormFile formFile)
        {
            // Find the video to update
            var video = await this.context.Videos.Where(v => v.Id == id).SingleOrDefaultAsync();
            if(formFile == null)
            {
                return this.BadRequest();
            }

            // Ensure that the service account has authorization
            var eventId = video.EventId;
            if (!await this.securityProvider.HasEventEditAccessAsync(eventId))
            {
                return this.Unauthorized();
            }

            // Attempt to deserialize the xml 
            int videoDuration = 0;

            try
            {
                var serializer = new XmlSerializer(typeof(AssetFiles));

                Stream stream = formFile.OpenReadStream();

                var assetFiles = (AssetFiles)serializer.Deserialize(stream);

                // Find duration and convert to seconds
                string durationString = assetFiles.AssetFile.Duration;
                TimeSpan durationTimeSpan = XmlConvert.ToTimeSpan(durationString);
                videoDuration = (int)durationTimeSpan.TotalSeconds;
            }
            catch(Exception ex)
            {
                return this.BadRequest();
            }

            // Update the video entry
            video.Duration = videoDuration;
            await this.context.SaveChangesAsync();

            return this.NoContent();

        }

最后,这是 MetadataProcessor 产生的 http 请求的原始读数,导致控制器中 formFile 的值为空:

POST http://localhost:5000/api/Events/UploadAzureEncodedMetadata/dc14829c-3d1b-4379-615b-08d5f8d07e16 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1OWNiODg5YS01YjRjLTRlMzUtOWMyOS0zYWQ3MGU4NTJhYTgiLCJqdGkiOiI5OTU3MWIyMy0xYTQwLTQ0OTUtOTE2Zi03NDY5YjYwYzI1N2MiLCJpYXQiOjE1MzM4MzM4NzAsIkV2ZW50UmVnVXNlciI6ZmFsc2UspOgHjFVudElkIjoiMTdhMjc4NDYtOTc1My00OGEzLTRlYzEtMDhkNGUxMjgwZjVhIiwibmJmIjoxNTMzODMzODcwLCJleHAiOjE1MzM4MzM5MzAsImlzcyI6IjYzYmVmM2NkYTM1OTRmZjBhOTdiYWFiYWJjYTQzODhmIiwiYXVkIjoiSW5mZXJub0NvcmUifQ.rhIjYRUtFjHWrrgd9XnmW4kMXaZ5UFyr2ApNK1EBJRI
Content-Type: multipart/form-data; boundary="1b6c2d6e-53d6-414c-bb1b-681ff9c766f0"
Content-Length: 2951
Host: localhost:5000

--1b6c2d6e-53d6-414c-bb1b-681ff9c766f0
Content-Disposition: form-data; name=formFile; filename="C:\tmp\17a27846-9753-48a3-4ec1-08d4e1280f5a\213e65ee-fff9-4668-b123-7d0746bb4b05\results\OUTPUT_ENCODER_213e65ee-fff9-4668-b123-7d0746bb4b05_00000000-0000-0000-0000-000000000000\a35f0612-7a07-4bec-a9fd-a61d2a2f71bb_metadata.xml"; filename*=utf-8''C%3A%5Ctmp%5C17a27846-9753-48a3-4ec1-08d4e1280f5a%5C213e65ee-fff9-4668-b123-7d0746bb4b05%5Cresults%5COUTPUT_ENCODER_213e65ee-fff9-4668-b123-7d0746bb4b05_00000000-0000-0000-0000-000000000000%5Ca35f0612-7a07-4bec-a9fd-a61d2a2f71bb_metadata.xml

<?xml version="1.0" encoding="utf-8"?>
<AssetFiles xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/windowsazure/mediaservices/2014/07/mediaencoder/inputmetadata">
  <AssetFile Name="bcff8e9a-7cb7-4d09-abd2-f04a83df1be1.mp4" Size="383631" Duration="PT5.568S" NumberOfStreams="2" FormatNames="mov,mp4,m4a,3gp,3g2,mj2" FormatVerboseName="QuickTime / MOV" StartTime="PT0S" OverallBitRate="551">
    <VideoTracks>
      <VideoTrack Id="1" Codec="h264" CodecLongName="H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10" TimeBase="1/90000" NumberOfFrames="166" StartTime="PT0S" Duration="PT5.533S" FourCC="avc1" Profile="Constrained Baseline" Level="3.0" PixelFormat="yuv420p" Width="560" Height="320" DisplayAspectRatioNumerator="0" DisplayAspectRatioDenominator="1" SampleAspectRatioNumerator="0" SampleAspectRatioDenominator="1" FrameRate="30" Bitrate="465" HasBFrames="0">
        <Disposition Default="1" Dub="0" Original="0" Comment="0" Lyrics="0" Karaoke="0" Forced="0" HearingImpaired="0" VisualImpaired="0" CleanEffects="0" AttachedPic="0" />
        <Metadata key="creation_time" value="2010-03-20T21:29:11.000000Z" />
        <Metadata key="language" value="und" />
        <Metadata key="encoder" value="JVT/AVC Coding" />
      </VideoTrack>
    </VideoTracks>
    <AudioTracks>
      <AudioTrack Id="2" Codec="aac" CodecLongName="AAC (Advanced Audio Coding)" TimeBase="1/48000" NumberOfFrames="261" StartTime="PT0S" Duration="PT5.568S" SampleFormat="fltp" ChannelLayout="mono" Channels="1" SamplingRate="48000" Bitrate="83" BitsPerSample="0">
        <Disposition Default="1" Dub="0" Original="0" Comment="0" Lyrics="0" Karaoke="0" Forced="0" HearingImpaired="0" VisualImpaired="0" CleanEffects="0" AttachedPic="0" />
        <Metadata key="creation_time" value="2010-03-20T21:29:11.000000Z" />
        <Metadata key="language" value="eng" />
      </AudioTrack>
    </AudioTracks>
    <Metadata key="major_brand" value="mp42" />
    <Metadata key="minor_version" value="0" />
    <Metadata key="compatible_brands" value="mp42isomavc1" />
    <Metadata key="creation_time" value="2010-03-20T21:29:11.000000Z" />
    <Metadata key="encoder" value="HandBrake 0.9.4 2009112300" />
  </AssetFile>
</AssetFiles>
--1b6c2d6e-53d6-414c-bb1b-681ff9c766f0--

我知道还有其他方法可以上传 xml 数据,但如果可能的话,我更愿意将 xml 解析保留在 api 方面。谢谢!

4

1 回答 1

0

当我从 IFormFile 参数中删除 [FromRoute] 属性并从 MVC 控制器中删除 [ApiController] 属性(代码中未显示)时,问题就解决了。为了不破坏控制器上的功能,我将专门为 UpdateDuration() 操作创建一个新控制器。

于 2018-08-09T19:52:26.043 回答