2

I'm having some trouble getting files to upload on a basic mvc project I'm working on... I have a drag/drop feature that I'd like to connect to aws s3. I I can get files into a local folder with the current application.. and have followed the steps here -> upload a file to amazon s3 super easy using c sharp -- to upload a single, specific file, with success. But, I cannot combine the two so that the files I drag/drop will end up in my bucket.

Below is all the code I have to date:

Index

@{
    ViewBag.Title = "Index";
}

<h2>Drag & Drop File Upload</h2>
<div id="dropArea">
    Drop your files here
</div>
<h4>Uploaded Files: </h4>
<ul class="list-group" id="uploadList">

</ul>

<style>
    #dropArea {
        background-image: url("http://xx.png"); 
        background-repeat: no-repeat;
        background-position: center;
        background-color:#fff;
        border: black dashed 1px;
        height: 500px;
        text-align: center;
        color: black;
    }
    .active-drop{
        background:#739cfb !important;
        border:solid 2px blue !important;
        opacity:.5;
        color:black !important;
    }
</style>

@section Scripts {
<script src="~/Scripts/jquery.filedrop.js"></script>
    <script type="text/javascript">
        $(function () {
            $('#dropArea').filedrop({
                url: '@Url.Action("UploadFiles")',
                allowedfiletypes: ['image/jpeg', 'image/png', 'image/gif'], 
                allowedfileextensions: ['.jpg', '.jpeg', '.png', '.gif'],
                paramname: 'files', 
                maxfiles: 5,
                maxfilesize: 5, // in MB
                dragOver: function () {
                    $('#dropArea').addClass('active-drop');
                    
                },
                dragLeave: function () {
                    $('#dropArea').removeClass('active-drop');
                },
                drop: function () {
                    $('#dropArea').removeClass('active-drop');
                },
                afterAll: function (e) {
                    $('#dropArea').html('file(s) uploaded successfully');

                },
                uploadFinished: function (i, file, response, time) {
                    $('#uploadList').append('<li class="list-group-item">'+file.name+'</li>')
                }
            })
        })
        </script>    
    }

Home Controller.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCDragDrop.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            AmazonS3Uploader amazonS3 = new AmazonS3Uploader();

            amazonS3.UploadFile();

            return View();
        }

        [HttpPost]
        public ActionResult UploadFiles(IEnumerable<HttpPostedFileBase> files)
        {

            foreach (var file in files) {
                string filePath = Guid.NewGuid() + Path.GetExtension(file.FileName);
                file.SaveAs(Path.Combine(Server.MapPath("~/UploadedFiles"), filePath));
            }

            return Json("file uploaded successfully");
        }
    }
}

AmazonS3Uploader.cs

using System;
using Amazon.S3;
using Amazon.S3.Model;

namespace MVCDragDrop
{
    public class AmazonS3Uploader
    {
        private string bucketName = "xxxxx";
        private string keyName = "";
        private string filePath = "";

        public void UploadFile()
        {
            var client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1);

            try {
                PutObjectRequest putRequest = new PutObjectRequest {
                    BucketName = bucketName,
                    Key = keyName,
                    FilePath = filePath,
                    ContentType = "plain/text"
                };

                PutObjectResponse response = client.PutObject(putRequest);
            }
            catch (AmazonS3Exception amazonS3Exception) {
                if (amazonS3Exception.ErrorCode != null &&
                    (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId")
                    ||
                    amazonS3Exception.ErrorCode.Equals("InvalidSecurity"))) {
                    throw new Exception("Check the provided AWS Credentials.");
                } else {
                    //throw new Exception("Error occurred: " + amazonS3Exception.Message);
                }
            }
        }
    }
}

My webconfig file is also set up with the correct s3 key/secret/profile name.

Any help would be much appreciated!

Thanks

wj1572
  • 23
  • 4
  • Shouldn't you be passing the path of the saved file to `amazonS3.UploadFile();`? While you are saving all the files to your local folder save their paths as well in an array which should be passed one by one to `amazonS3.UploadFile();` – Abdul Samad Sep 07 '17 at 07:04

1 Answers1

0

I will start in the same order as you have posted your question.

Index.cshtml

1) Please verify that the URL you are referring to in url: '@Url.Action("UploadFiles")' is correct. I believe it should be url: '@Url.Action("UploadFiles", "Home")'

2) Please verify that you have jquery added via a script tag.

HomeController.cs

1) Your Index function should only return a view.

2) Instantiate a new AmazonS3Uploader in the constructor.

3) Save all the file paths in a list, loop over them and pass each path to amazonS3.UploadFile(path)` for uploading to S3

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCDragDrop.Controllers
{
    public class HomeController : Controller
    {
        private AmazonS3Uploader amazonS3;

        public HomeController()
        {
            amazonS3 = new AmazonS3Uploader();
        }
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult UploadFiles(IEnumerable<HttpPostedFileBase> files)
        {
            List<string> paths = new List<string>();

            foreach (var file in files) {
                string filePath = Guid.NewGuid() + Path.GetExtension(file.FileName);
                string destPath = Path.Combine(Server.MapPath("~/UploadedFiles"), filePath);
                paths.Add(destPath)
                file.SaveAs(destPath);
            }

            foreach(var path in paths){
                amazonS3.UploadFile(path);
            }

            return Json("file uploaded successfully");
        }
    }
}

AmazonS3Uploader.cs

1) Instantiate the client object in your constructor.

2) Make changes to your UploadFile() method to accept a file path and use that path in PutObjectRequest

using System;
using Amazon.S3;
using Amazon.S3.Model;

namespace MVCDragDrop
{
    public class AmazonS3Uploader
    {
        private string bucketName = "xxxxx";
        private string keyName = "";
        private AmazonS3Client client;

        public AmazonS3Uploader()
        {
            client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1);
        }

        public void UploadFile(string filePath)
        {

            try {
                PutObjectRequest putRequest = new PutObjectRequest {
                    BucketName = bucketName,
                    Key = keyName,
                    FilePath = filePath,
                    ContentType = "plain/text"
                };

                PutObjectResponse response = client.PutObject(putRequest);
            }
            catch (AmazonS3Exception amazonS3Exception) {
                if (amazonS3Exception.ErrorCode != null &&
                    (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId")
                    ||
                    amazonS3Exception.ErrorCode.Equals("InvalidSecurity"))) {
                    throw new Exception("Check the provided AWS Credentials.");
                } else {
                    //throw new Exception("Error occurred: " + amazonS3Exception.Message);
                }
            }
        }
    }
}

Hope I could help :)

Abdul Samad
  • 441
  • 2
  • 11
  • Worked great, thanks!.. one more question.. how can I bypass the 'UploadedFiles' folder and go straight to s3? Now that I'm up and running, I'd like to be able to upload large files without the extra local backup. My goal is to upload from various external hard drives to s3. Much appreciated! – wj1572 Sep 08 '17 at 15:43
  • I believe It isn't possible to upload directly as the `PutRequestObject` requires the path to the file to be uploaded thus it is necessary to download/save the file before uploading. It would be nice to up vote and accept the answer if you found it helpfull :). Thanks. – Abdul Samad Sep 08 '17 at 17:10
  • 1
    And one more thing once the file is uploaded you can delete the file from your local temp folder by using `File.Delete(path)` to remove traces as you move forward :p – Abdul Samad Sep 08 '17 at 17:11