簡體   English   中英

在ASP.NET中重命名並發上載的文件

[英]Renaming concurrent uploaded files in ASP.NET

我使用以下代碼接收上傳的文件並將它們存儲在服務器上的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
    }
}

如何保證文件將以原子方式存儲和重命名?

而不是使用原始名稱然后重命名,為什么不在您的上傳代碼中動態生成名稱?

例如,如果文件顯示為“ foo.xml ”,則將其寫入磁盤“ BodyPart_be42560e-863d-41ad-8117-e1b634e928aa ”?

另請注意,如果您將文件上傳到"~/UploadedFiles"任何人都可以使用www.example.com/UploadedFiles/name.xml這樣的網址下載 - 您應該將文件存儲在~/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());
}

這應該將每個文件保存為唯一名稱,而不必稍后重命名。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM