使用GUID和文件扩展名上传ASP.NET WebApi文件

9

我可以保存上传到WebAPI控制器的文件,但我希望能将文件保存为GUID,并使用正确的文件扩展名,以便正确查看。

代码:

 [ValidationFilter]
    public HttpResponseMessage UploadFile([FromUri]string AdditionalInformation)
    {
        var task = this.Request.Content.ReadAsStreamAsync();
        task.Wait();

        using (var requestStream = task.Result)
        {
            try
            {
                // how can I get the file extension of the content and append this to the file path below?

                using (var fileStream = File.Create(HttpContext.Current.Server.MapPath("~/" + Guid.NewGuid().ToString())))
                {
                    requestStream.CopyTo(fileStream);
                }
            }
            catch (IOException)
            {                    
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            }
        }

        HttpResponseMessage response = new HttpResponseMessage();
        response.StatusCode = HttpStatusCode.Created;
        return response;
    }

我似乎无法掌握内容的实际文件名。我认为 headers.ContentDisposition.FileName 可能是一个候选项,但它似乎没有被填充。


这里有一个类似的问题,并附有答案https://dev59.com/lW7Xa4cB1Zd3GeqPrppS。 - forseta
你能分享一下你的请求头是什么样子的吗?你的请求中是否填充了ContentDisposition头? - Kiran
客户端应该负责设置这些标题。你的客户端是什么样子的? - Snixtor
@Kiran:不,它没有被填充。此外,所有的例子似乎都使用流提供程序来加载流。我想在不使用提供程序的情况下读取它,并将文件保存为GUID和扩展名。不使用流提供程序的原因是它似乎不允许我将为文件创建的GUID返回到调用函数。 - jaffa
1个回答

19

感谢上面的评论,它们指引了我朝着正确的方向。

为了澄清最终解决方案,我使用了一个MultipartFormDataStreamProvider,它可以自动流式传输文件。我的代码在这里发布到另一个问题中: MultipartFormDataStreamProvider和保留当前HttpContext

下面列出了我的完整提供程序代码。生成guid文件名的关键是覆盖GetLocalFileName函数并使用headers.ContentDisposition属性。提供程序会将内容流式传输到文件中。

public class MyFormDataStreamProvider : MultipartFormDataStreamProvider
{
    public MyFormDataStreamProvider (string path)
        : base(path)
    { }

    public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
    {
        // restrict what images can be selected
        var extensions = new[] { "png", "gif", "jpg" };
        var filename = headers.ContentDisposition.FileName.Replace("\"", string.Empty);

        if (filename.IndexOf('.') < 0)
            return Stream.Null;

        var extension = filename.Split('.').Last();

        return extensions.Any(i => i.Equals(extension, StringComparison.InvariantCultureIgnoreCase))
                   ? base.GetStream(parent, headers)
                   : Stream.Null;

    }

    public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
    {
        // override the filename which is stored by the provider (by default is bodypart_x)
        string oldfileName = headers.ContentDisposition.FileName.Replace("\"", string.Empty);
        string newFileName = Guid.NewGuid().ToString() + Path.GetExtension(oldfileName);

        return newFileName;       
    }
}

2
var filename = headers.ContentDisposition.FileName.Replace("\"", string.Empty); 会抛出空引用异常。通过在执行 Replace() 之前检查 filename 是否为 null 来解决该问题。 - Moses Machua
你为什么还要重写 GetStream 方法? - Fernando Torres

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接