【问题标题】:How to get the paramaters from an MVC MultipartFormData upload before the upload occurs如何在上传之前从 MVC 多部分表单数据上传中获取参数
【发布时间】:2013-08-24 08:00:53
【问题描述】:

我有一个 MVC web api,它接收表单上的附件,它还需要一个文本和整数字段来上传。这些字段是用于验证上传者的(字符串)userId 和用于将附件连接到数据库中的请求的(int)requestId。 目前它可以工作,但是对于多部分表单数据,我需要从请求中获取字段,而不是作为表单提交中的参数。我的问题是,当保存文件时,我需要使用 requestId(来自表单)和附件 ID(来自数据库)修改文件的名称,因此它读取(requestId)-(attachmentId)-(fileName)。我一直使用的方法涉及下载文件,然后从请求中获取数据,因为在初始化提供程序和下载的文件之前,它总是返回 null,然后在数据库和文件系统中重命名文件。我希望有人可能有更好的方法来做到这一点,这样我就可以一步完成使用适当变量的重命名。

这是我现在为我的控制器准备的东西

public async Task<HttpResponseMessage> PostFormData()
    {
        const string folderName = "uploads";
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException((HttpStatusCode.UnsupportedMediaType));
        }
        var rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
        // this is needed to create an attachment and get the attachment id for the file
        var value = new Attachment {UserId = "1", RequestId = 1};
        value = _dataManager.CreateNewAttachment(value);

        string root = HttpContext.Current.Server.MapPath("~/" + folderName);
        // this is where the provider gets initialized and also where the file is actually downloaded
        // in here I have it set up to rename the file but I can't seem to get the parameters needed for the file name before hand
        var provider = new CustomMultipartFormDataStreamProvider(root, value.CreditRequestId, value.Id);

        try
        {
            // this is the command that allows me to get the data from the inputs on the form, 
            // but it requires the initialized provider which downloaded the file to get it
            await Request.Content.ReadAsMultipartAsync(provider);
            // and here is wher I actually get the input parameters I needed
            foreach (var key in provider.FormData.AllKeys)
            {
                foreach (var val in provider.FormData.GetValues(key))
                {
                    //Trace.WriteLine(string.Format("{0}: {1}", key, val));
                    if (key == "requestId")
                    {
                        value.CreditRequestId = int.Parse(val);
                    }
                    if (key == "userId")
                    {
                        value.UserId = val;
                    }
                }
            }
            // below here is where I have it checking security against the userId, destroying the file if it is determined to be unsafe
            // and where I rename the file as well as modify the database with the proper content for the attachment

下面是我初始化以获取文件并更改名称的自定义多部分表单数据流提供程序,但在此之前我无法获取我需要正确执行此操作的参数,而无需重新访问文件并重命名它

public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
    public int RequestId;
    public int AttachmentId;

    public CustomMultipartFormDataStreamProvider(string path, int requestId, int attachmentId)
        : base(path)
    {
        RequestId = requestId;
        AttachmentId = attachmentId;
    }

    public override string GetLocalFileName(HttpContentHeaders headers)
    {
        //int requestId = 0;
        //int attachmentId = 0;
        var name = !string.IsNullOrEmpty(headers.ContentDisposition.FileName)
                       ? RequestId + "-" + AttachmentId + "-" + headers.ContentDisposition.FileName
                       : RequestId + "-" + AttachmentId + "-NoName";
        return name.Replace("\"", string.Empty);
    }

我已经搜索了谷歌并因此寻找答案,我想我有一些答案,但它们似乎没有用,我尝试从提供程序中获取数据,但它总是返回 null。 如果有人对此有解决方案,将不胜感激

【问题讨论】:

    标签: asp.net-mvc file-upload webforms asp.net-web-api multipartform-data


    【解决方案1】:

    所以我设法弄清楚了,以防其他人自己寻找答案 我在创建文件之前查询了 ​​httpContext,使用 web api 它仍然能够读取从 UI 发送的表单数据

     public async Task<HttpResponseMessage> PostFormData()
        {
            const string folderName = "uploads";
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException((HttpStatusCode.UnsupportedMediaType));
            }
            var rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
    
            // this is where I get the form information now prior to actually recieving the file
            int requestId = int.Parse(HttpContext.Current.Request.Form["requestId"]);
            string userId = HttpContext.Current.Request.Form["userId"];
    
    
            var value = new Attachment {UserId = userId, RequestId = requestId};
            value = _dataManager.CreateNewAttachment(value);
    
    
            string root = HttpContext.Current.Server.MapPath("~/" + folderName);
    
            var provider = new CustomMultipartFormDataStreamProvider(root, value.RequestId, value.Id);
    
            try
            {
    
                await Request.Content.ReadAsMultipartAsync(provider);
    
                var httpRequest = HttpContext.Current.Request;
    
                foreach (string file in httpRequest.Files)
                {
                var postedFile = httpRequest.Files[file];
                var filePath = rootUrl + "/" + folderName + "/";
    
                value.Path = filePath + value.RequestId + "-" + value.Id + "-" + postedFile.FileName;
                value.FileName = value.RequestId + "-" + value.Id + "-" + postedFile.FileName;
    
                }
    

    毕竟,我可以包含我的业务逻辑来确定文件是否安全,并且我不必在文件上调用移动函数来在服务器上重命名它。它也使它更加稳定。

    【讨论】:

      猜你喜欢
      • 2015-06-14
      • 1970-01-01
      • 2020-05-17
      • 1970-01-01
      • 2013-05-01
      • 2016-11-03
      • 2014-08-18
      • 1970-01-01
      相关资源
      最近更新 更多