0

I have an issue with the web api (again). I want to upload a file to my s3 bucket, currently I do this through a normal controller which looks like this:

public class _UploadController : BaseController
{
    public JsonNetResult StartUpload(string id, HttpPostedFileBase file)
    {
        try
        {
            using (var service = new ObjectService(ConfigurationManager.AppSettings["AWSAccessKey"], ConfigurationManager.AppSettings["AWSSecretKey"], this.CompanyId))
            {
                if (!service.Exists(file.FileName))
                {
                    service.Add(id);

                    var stream = new MemoryStream();
                    var caller = new AsyncMethodCaller(service.Upload);

                    file.InputStream.CopyTo(stream);

                    var result = caller.BeginInvoke(id, stream, file.FileName, new AsyncCallback(CompleteUpload), caller);
                }
                else
                    throw new Exception("This file already exists. If you wish to replace the asset, please edit it.");

                return new JsonNetResult { Data = new { success = true } };
            }
        } catch(Exception ex)
        {
            return new JsonNetResult { Data = new { success = false, error = ex.Message } };
        }
    }

    public void CompleteUpload(IAsyncResult result)
    {
        using (var service = new ObjectService(ConfigurationManager.AppSettings["AWSAccessKey"], ConfigurationManager.AppSettings["AWSSecretKey"], this.CompanyId))
        {
            var caller = (AsyncMethodCaller)result.AsyncState;
            var id = caller.EndInvoke(result);

            //this.service.Remove(id);
        }
    }

    //
    // GET: /_Upload/GetCurrentProgress

    public JsonResult GetCurrentProgress(string id)
    {
        try
        {
            var bucketName = this.CompanyId;
            this.ControllerContext.HttpContext.Response.AddHeader("cache-control", "no-cache");

            using (var service = new ObjectService(ConfigurationManager.AppSettings["AWSAccessKey"], ConfigurationManager.AppSettings["AWSSecretKey"], bucketName))
            {
                return new JsonResult { Data = new { success = true, progress = service.GetStatus(id) } };
            }
        }
        catch (Exception ex)
        {
            return new JsonResult { Data = new { success = false, error = ex.Message } };
        }
    }
}

This works fine, but I want to create an web api to handle the uploads. The web api version didn't work (Unsupported media type when uploading using web api)

So I started looking at tutorials. I came across this method:

public async Task<HttpResponseMessage> PostFile()
{
    // Check if the request contains multipart/form-data.
    if (!Request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }

    string root = HttpContext.Current.Server.MapPath("~/App_Data");
    var provider = new MultipartFormDataStreamProvider(root);

    try
    {
        StringBuilder sb = new StringBuilder(); // Holds the response body

        // Read the form data and return an async task.
        await Request.Content.ReadAsMultipartAsync(provider);

        // This illustrates how to get the form data.
        foreach (var key in provider.FormData.AllKeys)
        {
            foreach (var val in provider.FormData.GetValues(key))
            {
                sb.Append(string.Format("{0}: {1}\n", key, val));
            }
        }

        // This illustrates how to get the file names for uploaded files.
        foreach (var file in provider.FileData)
        {
            FileInfo fileInfo = new FileInfo(file.LocalFileName);
            sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length));
        }
        return new HttpResponseMessage()
        {
            Content = new StringContent(sb.ToString())
        };
    }
    catch (System.Exception e)
    {
        return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
    }
}

The problem with this, is that it saves the file to ~/App_Data by creating a MultipartFormDataStreamProvider and reading the Content asynchronously. What I would like to do is capture the data and store it in a memory stream and then upload it to s3.

Is that possible? I don't want to upload my file to my server and then to s3.

Community
  • 1
  • 1
r3plica
  • 13,017
  • 23
  • 128
  • 290

1 Answers1

0

There is a similar StackOverflow question here: Is it possible to override MultipartFormDataStreamProvider so that is doesn't save uploads to the file system?

The answer here should help you.

Community
  • 1
  • 1
mugdhak
  • 31
  • 3