简体   繁体   中英

Post Text values and upload an image by Web Api 2 C#

I'm trying to save some data to my database and uploading an image at the same time using a Web Api.

I failed to do this because I cannot send multipart/from and JSON at the same time. I got this error:

request entity's media type 'multipart/form-data' is not supported for this resource.

This is my code:

public IHttpActionResult Post([FromBody]Post userpost)
{
   Upload upload = new Upload();
   int postid = Convert.ToInt32(postDB.AddPost(userpost));                   
   var filename = postid + "_"+Guid.NewGuid().ToString();
   upload.UploadFile(filename, Request);
   return Ok(HttpStatusCode.Accepted);
}

public class Upload:IUpload
{
    private const string Container = "images";

    public async Task<bool> UploadFile(string filename, HttpRequestMessage Request)
    {
        var accountName = ConfigurationManager.AppSettings["storage:account:name"];

        var accountKey = ConfigurationManager.AppSettings["storage:account:key"];
        var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        CloudBlobContainer imagesContainer = blobClient.GetContainerReference(Container);

        var provider = new AzureImages(imagesContainer,filename);

        try
        {
            await Request.Content.ReadAsMultipartAsync(provider);
        }
        catch (Exception ex)
        {
            return false;
        }

        if (string.IsNullOrEmpty(filename))
        {
            return false;
        }

        return true;
    }
}
}

I'm testing it using Postman Thanks in advance.

create a view model to handle your entire posted information.

public class CombinedPostAndImage
{
    /* your post properties */
    public intProperty1 { get;set; }
    public string Propert2 { get;set; }
    ...
    public string FileName { get; set; }
    /* this example is using a Base64String
    public string FileBody { get; set; }
}

change your controller action to accept this new type.

public IHttpActionResult Post(CombinedPostAndImage combinedPost)
{
  /* create your Post from the combinedPost  */
    var post = new Post
    {
        post.Property1 = combinedPost.Property1,
        /* more properties */
    };

    int postid = Convert.ToInt32(postDB.AddPost(userpost));

    var filename= string.Format("{0}_{1}", postid, Guid.NewGuid().ToString());

        //Convert Base64 Encoded string to Byte Array.
    using (var ms = new MemoryStream(Convert.FromBase64String(combinedPost.FileBody)))
    {
        var uploader = new Upload();
        uploader.UploadFile(filename, ms);
    }
}

Per you update I would change the UploadFile method to take a stream. Like

public async Task<bool> UploadFile(string filename, Stream uploadStream)
{       
   var accountName = ConfigurationManager.AppSettings["storage:account:name"];

    var accountKey = ConfigurationManager.AppSettings["storage:account:key"];
    var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
    CloudBlobContainer imagesContainer = blobClient.GetContainerReference(Container);

    CloudBlockBlob blockBlob = imagesContainer.GetBlockBlobReference(filename);

    blockBlob.UploadFromStream(uploadStream);
}  

I'm not familiar with the Azure SDK, but from the documentation online, you probably want something like this.

I wouldn't tie my Azure uploader to the Request stream. I'd also pass the Upload(er) class to my controller's constructor since it a required dependency that can be satisfied through an IoC container.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM