【问题标题】:Expected end of MIME multipart stream. MIME multipart message is not completeMIME 多部分流的预期结束。 MIME 多部分消息不完整
【发布时间】:2017-05-12 15:13:24
【问题描述】:

我有一个 Angular 应用程序,用 Typescript 编写,带有 ASP.Net Web Api 后端。我正在尝试使用 ng-file-upload(有关详细信息,请参阅此 link)指令来上传图像文件。

我在我的 Web API Post 方法中收到异常:

“MIME 多部分流意外结束。MIME 多部分消息不完整。”

我已经完成了我的研究并发现了类似的问题here - 我尝试实施 Landuber Kassa 的答案,但没有成功。

还有this,虽然我的项目不是 MVC,而且无论如何它都不起作用。

我的想法很新鲜,我很欣赏社区的想法。如果我能指出正确的方向,我很乐意考虑任何其他替代方案。

我的 .Net Post 方法(实现 Landuber Kassa 的想法):

[RoutePrefix("BeaufortAppStore/api/Image")]
public class ImageController : ApiController
{

    #region Methods

    #region Posts

    [Route("UploadImage")]
    [HttpPost]
    public async Task<IHttpActionResult> UploadImage()
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        var provider = new MultipartMemoryStreamProvider();

        Stream reqStream = Request.Content.ReadAsStreamAsync().Result;
        MemoryStream tempStream = new MemoryStream();
        reqStream.CopyTo(tempStream);

        tempStream.Seek(0, SeekOrigin.End);
        StreamWriter writer = new StreamWriter(tempStream);
        writer.WriteLine();
        writer.Flush();
        tempStream.Position = 0;

        StreamContent streamContent = new StreamContent(tempStream);
        foreach (var header in Request.Content.Headers)
        {
            streamContent.Headers.Add(header.Key, header.Value);
        }

        // Read the form data and return an async task.
        await streamContent.ReadAsMultipartAsync(provider); // FAILS AT THIS POINT
        foreach (var file in provider.Contents)
        {
            var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
            var buffer = await file.ReadAsByteArrayAsync();
            //Do whatever you want with filename and its binary data.
        }
        return Ok();
    }

    #endregion

    #endregion

我的角度控制器方法:

public upload(): void {
        //Create config used in ng-file-upload
        var config: IFileUploadConfigFile = {
            data: this.file, url: "BeaufortAppStore/api/Image/UploadImage/", method: "POST" };
        this._dataService.uploadImage(config).then((result: any) => {
            this.thumbnail = result.data;
        });
    }

我的角度视图(指令的部分视图):

<div class="form-group">
<label for="file" class="control-label col-xs-2">Choose a file</label>
<input id="file" type="file" name="file" class="form-control" ngf-select ngf-pattern="'image/*'"
       ng-model="vm.file" />
<img style="width:100px;" ngf-thumbnail="thumbnail || '/thumb.jpg'" />
<button type="submit" ng-click="vm.upload()">Upload</button>

【问题讨论】:

  • 关于这个问题的任何更新?我在上传文件时也遇到了同样的情况。如果您找到任何解决方案,分享会很有帮助。

标签: c# angularjs asp.net-web-api ng-file-upload


【解决方案1】:

在 C# 中试试这个:

    [HttpPost]
    [Route("Profile/Image")]
    public Task<HttpResponseMessage> UploadImgProfile()
            {
                try
                {
                    if (!ModelState.IsValid) return null;

                    var currentUser = _userUtils.GetCurrentUser(User);
                    if (currentUser == null) return null;

                    HttpRequestMessage request = this.Request;
                    if (!request.Content.IsMimeMultipartContent())
                        throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType));

                    string root = HttpContext.Current.Server.MapPath("~" + Constant.Application.User_Image_Directory);

                    bool exists = Directory.Exists(root);
                    if (!exists)
                        Directory.CreateDirectory(root);

                    var provider = new   MultipartFormDataStreamProvider(root);





     var task = request.Content.ReadAsMultipartAsync(provider).
                    ContinueWith<HttpResponseMessage>(o =>
                    {
                        var finfo = new     FileInfo(provider.FileData.First().LocalFileName);

          string guid = Guid.NewGuid().ToString();

          var fileName = guid + "_" + currentUser.IdOwin + ".jpg"; 

                        File.Move(finfo.FullName, Path.Combine(root, fileName));

                        return new HttpResponseMessage()
                        {
                            Content = new StringContent(Path.Combine(Constant.Application.User_Image_Directory, fileName))
                        };
                        }
                        );
                    return task;
                }
                catch (Exception ex)
                {
                    _logger.LogException(ex);
                    return null;
                }
            }

角度控制器:

 //Upload Func
            $scope.upload = function (files) {
                if (files && files.length) {
                    for (var i = 0; i < files.length; i++) {
                        var file = files[i];
                        $scope.uploading = true;
                        //   $scope.imageName = file.name;
                        $upload.upload({
                            url: enviroment.apiUrl + '/api/CurrentUser/Profile/Image',
                            //fields: { 'username': $scope.username },
                            file: file
                        }).progress(function (evt) {
                            $scope.uploading = true;
                            var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
                            console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
                            $scope.progress = progressPercentage;
                        }).success(function (data, status, headers, config) {
                            console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
                            $scope.imageName = data;
                            $scope.uploading = false;
                            $scope.loadSuccess = true;
                            vm.uploadImage = false;
                            //AR
                            var reader = new FileReader();
                            reader.onload = function (evt) {
                                $scope.$apply(function ($scope) {
                                    $scope.myImage = evt.currentTarget.result;
                                });
                            };
                            reader.readAsDataURL(files[0]);
                            //END AR
                        });
                    }
                }
            };


    // Stay on Listen upload file
    $scope.$watch('files', function (evt) {
        $scope.upload($scope.files);
    });

HTML:

 <div class="row">
                                <!--UPLOAD-->
                                <div class="up-buttons">

                                    <div class="clearfix visible-xs-block"></div>
                                    <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center box-upload-image" data-ng-show="profileCtrl.uploadImage">
                                        <br />
                                        <div id="imgDragDrop" ng-file-drop ng-model="files"
                                             drag-over-class="dragover"
                                             accept="image/*">

                                            <div class="cropArea-bkg">
                                                <h4>
                                                    <span class="mdi mdi-account mdi-48px"></span>
                                                    <br /><br />
                                                    Carica immagine profilo
                                                </h4>

                                                <p>Trascina qui la tua immagine, oppure</p>

                                                <div ng-file-select="" ng-model="files" class="btn btn-secondary" ng-accept="'*.pdf,*.jpg,*.png'" tabindex="0">
                                                    Sfoglia sul tuo computer
                                                </div><br>
                                            </div>
                                        </div>
                                        <div ng-no-file-drop class="well bg-danger">File Drag/Drop non è supportato da questo browser</div>
                                        <br />
                                        <div class="text-center">
                                            <div class="progress" ng-show="uploading">
                                                <div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="{{ ::progress }}" aria-valuemin="0" aria-valuemax="100" style="width: {{::progress}}% ">
                                                    <span class="sr-only">{{ ::progress }}% Complete</span>
                                                </div>
                                            </div>
                                        </div>

                                    </div>

                                    <!--END UPLOAD-->

                                </div>
                            </div>

【讨论】:

  • 感谢您的快速回答。在我尝试之前,您能否解释一下这种方法的不同之处。
  • 基本上,这是一种经过实战考验的方法,可以从角度上传中检索多部分上传内容......它从 this.Request 中采用正确的格式,并通过异步任务生成一个名称(随机如果有人上传具有相同名称的相同图像,则指导不要覆盖或进入异常)
  • 如果您需要,我还会向您展示控制器 (Angular) 和 html..并确保您的发布方法(在 chrome 控制台上检查..如果格式正确..如果不尝试覆盖请求的标头)
  • 是的,请给我控制器和html,我会试着把它们放在一起
  • 好的我编辑答案..它不是打字稿..我希望你能重新安排它
猜你喜欢
  • 1970-01-01
  • 2022-07-12
  • 2016-12-31
  • 2021-05-18
  • 2013-12-10
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2014-09-07
相关资源
最近更新 更多