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.