【问题标题】:Renaming concurrent uploaded files in ASP.NET在 ASP.NET 中重命名并发上传的文件
【发布时间】:2014-01-01 00:17:43
【问题描述】:

我使用下面的代码来接收上传的文件,并将它们存储在服务器上的uploadedFiles文件夹中。

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

    public override string GetLocalFileName(HttpContentHeaders headers)
    {
        return headers.ContentDisposition.FileName.Replace("\"", string.Empty);
    }
}

[HttpPost]
public async Task<HttpResponseMessage> ReceiveFileupload()
{
    if (!Request.Content.IsMimeMultipartContent("form-data"))
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);

    // Prepare CustomMultipartFormDataStreamProver in which our multipart form data will be loaded
    string fileSaveLocation = HttpContext.Current.Server.MapPath("~/UploadedFiles");
    CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(fileSaveLocation);
    List<string> files = new List<string>();
    Duck duck = null;

    try
    {
        // Read all contents of multipart message into CustomMultipartFormDataStreamProvider
        await Request.Content.ReadAsMultipartAsync(provider);

        // Parse an ID which is passed in the form data
        long id;
        if (!long.TryParse(provider.FormData["id"], out id))
        {
            return Request.CreateResponse(HttpStatusCode.ExpectationFailed, "Couldn't determine id.");
        }

        duck = db.Ducks.Find(id);
        if (null == duck)
            return Request.CreateResponse(HttpStatusCode.NotAcceptable, "Duck with ID " + id + " could not be found.");

        // Loop through uploaded files
        foreach (MultipartFileData file in provider.FileData)
        {
            // File ending needs to be xml
            DoSomething();

            // On success, add uploaded file to list which is returned to the client
            files.Add(file.LocalFileName);
        }

        // Send OK Response along with saved file names to the client.
        return Request.CreateResponse(HttpStatusCode.OK, files);
    }

    catch (System.Exception e) {
        return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
    }
}

现在我想重命名上传的文件。据我了解,存储和重命名必须在关键部分完成,因为当另一个用户同时上传同名文件时,第一个将被覆盖。

这就是我想象的解决方案,但是锁定语句中不允许使用await。

lock(typeof(UploadController)) {
    await Request.Content.ReadAsMultipartAsync(provider);  //That's the line after which the uploaded files are stored in the folder.
    foreach (MultipartFileData file in provider.FileData)
    {
        RenameFile(file); // Rename according to file's contents
    }
}

我如何保证文件将被自动存储和重命名?

【问题讨论】:

  • 为什么不将文件创建为元组 第一个字符串是原始文件名(file.LocalFileName),第二个字符串是所需(重命名)文件名

标签: c# asp.net asp.net-mvc file-upload multipartform-data


【解决方案1】:

为什么不在您的上传代码中即时生成名称,而不是使用原始名称然后重命名?

例如如果文件显示为“foo.xml”,则将其写入磁盘为“BodyPart_be42560e-863d-41ad-8117-e1b634e928aa”?

另外请注意,如果您将文件上传到 "~/UploadedFiles",任何人都可以使用类似 www.example.com/UploadedFiles/name.xml 的 URL 下载它 - 您应该将文件存储在 ~/App_Data/ 以防止这种情况发生。

更新:

为什么不删除您对GetLocalFileName 方法的覆盖,而只使用MultipartFileStreamProvider 基类中的原始方法?

public virtual string GetLocalFileName(HttpContentHeaders headers)
{
    if (headers == null)
    {
        throw Error.ArgumentNull("headers");
    }

    return String.Format(CultureInfo.InvariantCulture, "BodyPart_{0}", Guid.NewGuid());
}

这应该将每个文件保存为唯一的名称,而无需以后重命名。

【讨论】:

  • @Explicat:答案已更新。如果您需要进一步的帮助,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-13
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 2017-12-26
  • 2015-02-21
  • 2013-07-02
相关资源
最近更新 更多