javascript - 一键上传文件并发布文本输入值?

标签 javascript c# html asp.net-web-api forms

我正在尝试构建一个用于发布文件的 Asp.net Web api。我在中找到了以下示例 https://code.msdn.microsoft.com/AngularJS-with-Web-API-22f62a6e

Web API 方法是:

[RoutePrefix("api/photo")]
public class PhotoController : ApiController
{
    private IPhotoManager photoManager;

    public PhotoController()
        : this(new LocalPhotoManager(HttpRuntime.AppDomainAppPath + @"\Album"))
    {            
    }

    public PhotoController(IPhotoManager photoManager)
    {
        this.photoManager = photoManager;
    }

    // GET: api/Photo
    public async Task<IHttpActionResult> Get()
    {
        var results = await photoManager.Get();
        return Ok(new { photos = results });
    }

    // POST: api/Photo
    public async Task<IHttpActionResult> Post()
    {
        // Check if the request contains multipart/form-data.
        if(!Request.Content.IsMimeMultipartContent("form-data"))
        {
            return BadRequest("Unsupported media type");
        }

        try
        {
            var photos = await photoManager.Add(Request);
            return Ok(new { Message = "Photos uploaded ok", Photos = photos });
        }
        catch (Exception ex)
        {
            return BadRequest(ex.GetBaseException().Message);
        }

    }

文件 uploader html 代码:(我添加了一个文本输入 <input type="text" id="test" value="testit" /> 进行测试。

<form name="newPhotosForm" role="form" enctype="multipart/form-data" ng-disabled="appStatus.busy || photoManagerStatus.uploading">
    <div class="form-group" ng-hide="hasFiles">
        <label for="newPhotos">select and upload new photos</label>
        <input type="file" id="newPhotos" class="uploadFile" accept="image/*" eg-files="photos" has-files="hasFiles" multiple>
        <input type="text" id="test" value="testit" /> <!--- Added a text input for test -->
    </div>
    <div class="form-group" ng-show="hasFiles && !photoManagerStatus.uploading">
        <ul class="list-inline">
            <li><strong>files:</strong></li>
            <li ng-repeat="photo in photos"> {{photo.name}}</li>
        </ul>
        <input class="btn btn-primary" type="button" eg-upload="upload(photos)" value="upload">
        <input class="btn btn-warning" type="reset" value="cancel" />
    </div>
    <div class="form-group" ng-show="photoManagerStatus.uploading">
        <p class="help-block">uploading</p>
    </div>
</form>

JS upload功能:

function upload(photos)
{
    service.status.uploading = true;
    appInfo.setInfo({ busy: true, message: "uploading photos" });            

    var formData = new FormData();

    angular.forEach(photos, function (photo) {
        formData.append(photo.name, photo);
    });

    return photoManagerClient.save(formData)
                                .$promise
                                .then(function (result) {
                                    if (result && result.photos) {
                                        result.photos.forEach(function (photo) {
                                            if (!photoExists(photo.name)) {
                                                service.photos.push(photo);
                                            }
                                        });
                                    }

                                    appInfo.setInfo({message: "photos uploaded successfully"});

                                    return result.$promise;
                                },
                                function (result) {
                                    appInfo.setInfo({message: "something went wrong: " + result.data.message});
                                    return $q.reject(result);
                                })
                                ['finally'](
                                function () {
                                    appInfo.setInfo({ busy: false });                                            
                                    service.status.uploading = false;
                                });
}

但是好像添加的输入值test无法传递给Web API代码?

最佳答案

您需要添加自定义 DTO/POCO 类,设置值,然后将其作为参数传递给您的 post 方法。由于文件不是简单类型,webAPI 的默认 MediaTypeFormatter 将无法工作,因此您需要构建自定义 MediaTypeFormatter。

POCO 类示例

Public Class Attachment
{
    public string Input {get;set;}
    public byte[] Content{get;set;}
} 

自定义媒体格式化程序如下

public class CustomFormatter : MediaTypeFormatter
{
    /// <summary>
    /// 
    /// </summary>
    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"); 

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

        var fileContents = provider.Contents
            .Where(c => c.Headers.ContentType.MediaType == "image/jpeg").FirstOrDefault(); // or whatever is the type of file to upload

        attachment.Content = await fileContents.ReadAsByteArrayAsync();

        return attachment;

    }
}

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

private void ConfigureWebApi(HttpConfiguration config)
{
    //other code here
    config.Formatters.Add(new CustomFormatter());
}   

将 POCO 传递到您的 Web-API Controller

public async Task<IHttpActionResult> Post(Attachment attachment)
{

我尚未在 Visual Studio 中对此进行测试,但这是您需要遵循的方法

更多信息请点击这里: 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

关于javascript - 一键上传文件并发布文本输入值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39673026/

相关文章:

javascript - JS 递归查找父子数组中的元素

javascript - react /归零 : mapStateToProps not actually mapping state to props

c# - Win32Exception:访问在 System.Diagnostics.ProcessManager.OpenProcess() 中被拒绝

c# - 如何获取Appium中的元素列表

java - 使用 jquery 创建的表无法从 servlet 访问

html - 分机号 : How to write custom styles CSS/SCSS for Grid column header?

javascript - ejs中不能for循环

javascript - 如何在 ionic 中显示 Javascript 文件中的数据?

c# - 我为什么要购买 ReSharper 或 CodeRush?

java - ITextRenderer.setDocumentFromString(html) 导致 javax.xml.transform.TransformerException