0

I'm using uploadify in my MVC3 project. It works fine to upload multiple files and saving to folders as well.

How to pass the path of the uploaded file to controller action ? -- I need to pass it to the ExtractingZip action of my controller.

To extract the contents of the .zip file, I'm using DotNetZip Library.

Here is what i've tried so far.

$('#file_upload').uploadify({
            'checkExisting': 'Content/uploadify/check-exists.php',
            'swf': '/Content/uploadify/uploadify.swf',
            'uploader': '/Home/Index',
            'auto': false,
            'buttonText': 'Browse',
            'fileTypeExts': '*.jpg;*.jpeg;*.png;*.gif;*.zip',
            'removeCompleted': false,
            'onSelect': function (file) {
                if (file.type == ".zip") {
                    debugger;
                    $.ajax({
                        type: 'POST',
                        dataType: 'json',
                        url: '@Url.Action("ExtractingZip", "Home")',
                        data: ({ fileName: file.name}), // I dont see a file.path to pass it to controller
                        success: function (result) {
                            alert('Success');
                        },
                        error: function (result) {
                            alert('error');
                        }
                    });
                }

            }
});

Here is my controller action:

   [HttpPost]
            public ActionResult ExtractingZip(string fileName,string filePath, HttpPostedFileBase fileData)
            {

                string zipToUnpack = @"C:\Users\Public\Pictures\Sample Pictures\images.zip";// I'm unable to get the filePath so i'm using the path.
                string unpackDirectory = System.IO.Path.GetTempPath();

                using (ZipFile zip1 = ZipFile.Read(zipToUnpack))
                {
                    // here, we extract every entry, but we could extract conditionally
                    // based on entry name, size, date, checkbox status, etc.  
                    var collections = zip1.SelectEntries("name=*.jpg;*.jpeg;*.png;*.gif;");

                    foreach (var item in collections)
                    {
                        item.Extract(unpackDirectory, ExtractExistingFileAction.OverwriteSilently);
                    }
                }
                return Json(true);
            }

[HttpPost]
        public ActionResult Index(IEnumerable<HttpPostedFileBase> fileData)
        {

                foreach (var file in fileData)
                {
                    if (file.ContentLength > 0)
                    {
                        string currpath;

                        currpath = Path.Combine(Server.MapPath("~/Images/User3"), file.FileName);
                        //save to a physical location
                        file.SaveAs(currpath);
                    }
                }
        }
Karthik Chintala
  • 5,465
  • 5
  • 30
  • 60
  • How attached are you to uploadify? – Ben Tidman Dec 17 '12 at 14:08
  • No. I'm just a beginner to uploadify. But If i dont use `onSelect` in uploadify i can read the .zip file data with HttpPostedFileBase – Karthik Chintala Dec 17 '12 at 14:11
  • So you are using onselect to try and make this an ajax request? I've never used Uploadify myself, but I got the impression that ajax was the default submission behavior. – Ben Tidman Dec 17 '12 at 14:16
  • Yes exactly. if i dont use `onSelect` and when i place a debugger at `Index` it fires when file is uploaded and i could see the data as well and save it. – Karthik Chintala Dec 17 '12 at 14:18
  • So why are you trying to use onselect? Or is your problem solved now? – Ben Tidman Dec 17 '12 at 14:19
  • If the selected file is a .zip file i want to extract all the `images` from it, that is what the reason to use `onSelect` in uploadify – Karthik Chintala Dec 17 '12 at 14:21
  • Hang on though. If you don't use the onSelect, you do get the file contents.. I.E. fileData is not null? So then does the solution that I posted for you work? You should just be able to use fileData.InputStream now right? – Ben Tidman Dec 17 '12 at 14:24
  • Yes. I'm unable to get `fileData.InputStream` in the intellisense. – Karthik Chintala Dec 18 '12 at 04:44
  • Thats strange. What version of .net does your project target. That property should be there unless you are targeting .net 3.0 or less http://msdn.microsoft.com/en-us/library/system.web.httppostedfilebase.inputstream(v=vs.100).aspx – Ben Tidman Dec 18 '12 at 12:55
  • .net 4.0 is my project version – Karthik Chintala Dec 18 '12 at 12:58
  • and fileData is still of type HttpPostedFileBase and it's not null? – Ben Tidman Dec 18 '12 at 13:00
  • Hey i could get fileData.InputStream – Karthik Chintala Dec 18 '12 at 13:00
  • Great, give it a run, and let me know if that works – Ben Tidman Dec 18 '12 at 13:02
  • Yes it is of `HttpPostedFileBase`, and its null when i debug. If i wont specify `onSelect` i could see the fileData is not null. If i give through $.ajax fileData is null – Karthik Chintala Dec 18 '12 at 13:04
  • Trying to understand. Why do you need onSelect? Isn't the default behavior of Uploadify to make ajax requests? – Ben Tidman Dec 18 '12 at 13:07
  • Actually if i upload a `.zip` file, it should automatically throw me all the image files in the `.zip` file. So, if i use onSelect i could sort out all the image files in the zip file. I dont understand what is the parameter to pass to the controller action so that i can get desired – Karthik Chintala Dec 18 '12 at 13:10
  • hm.. trying to understand. It looks like you have some c# code to unpack your zip so that you can work with the individual images in your c# code. Are you trying to unpack the zip before you send it to your controller? How come? – Ben Tidman Dec 18 '12 at 13:16
  • No, If i could see the data in my controller action i can unzip to some temp file. After sending the data to controller it will unzip or unpack the zip file to someother location – Karthik Chintala Dec 18 '12 at 13:17
  • Okay I'm still trying to understand. When you don't use Onselect, you get the file data in your controller action right? That is the file data for the zipped file you are uploading isn't it? So I don't understand what you still need help with. Just don't use OnSelect and you should be able to unpack the zip in your controller. – Ben Tidman Dec 18 '12 at 13:29
  • Yes, i could do that but i need to display the files in .zip file that are to be uploaded – Karthik Chintala Dec 18 '12 at 13:31
  • Is it okay to display the images after they are uploaded? If so I would recommend this path: upload the zip to controller action, unpack the zip and save contents however you want, use this event on uploadify http://www.uploadify.com/documentation/uploadify/onuploadcomplete/ to know when the upload is finished. Make an ajax request, or navigate the user to a new page that returns all the images that were in the zip. From there you can add other action like the ability to delete images that you don't want etc. Either that... or just have your users unpack the zip themselves!!! :) – Ben Tidman Dec 18 '12 at 13:37

2 Answers2

0

You don't need to pass the zip's filepath when it's uploaded. The filepath would be from the clients machine right? Your application on your server has no knowledge or access to the clients file system.

The good news is you don't need it. You already have the contents of your file in memory. I have never used donetzip but some quick googling reveals that you can read zips directly from a stream.

Check out these links:

Cannot read zip file from HttpInputStream using DotNetZip 1.9

Extracting zip from stream with DotNetZip

So using those posts as a base to go off of... It looks like you should be able to change your code like so:

            string zipToUnpack = @"C:\Users\Public\Pictures\Sample Pictures\images.zip";// I'm unable to get the filePath so i'm using the path.
            string unpackDirectory = System.IO.Path.GetTempPath();

            using (ZipFile zip1 = ZipFile.Read(zipToUnpack))
            {
                ....

Changes to...

            string unpackDirectory = System.IO.Path.GetTempPath();

            using (ZipFile zip1 = ZipFile.Read(fileData.InputStream))
            {
                ....

Let me know if that helps.

Community
  • 1
  • 1
Ben Tidman
  • 2,129
  • 17
  • 30
0

First of, due to security reasons you have no access directly to clients machine. While a user uploads some files, web browsers make one or tow (usually 1, according to RFC) stream and server-side script reads that stream, so do not waste your time to get files directly from user's local machine's filepath.

To extract archives (s.a: Zip, Rar) I highly recommend you to use SevenZipSharp. It works really good and easy with Streams and also many compression formats.

As they documentation you can extract stream like this:

using (MemoryStream msin = new MemoryStream(fileData.InputStream)) 
{ ... }
Alireza
  • 142
  • 1
  • 4
  • 13
  • Thankyou. Can i extract only specified formats with SevenZipSharp. I mean is if .zip file contains all images. I only need to get .jpg files. Is that possible? – Karthik Chintala Dec 17 '12 at 13:50
  • @Karthik To do this you should search inside a collection of archive's files. SevenZip.SevenZipExtractor.ArchiveFileData property gives you a collection of filenames. You can search inside of collection and select which file to extract (download and read the documentation). – Alireza Dec 17 '12 at 20:04
  • I dont find any documentation for SevenZipSharp on [Codeplex](http://sevenzipsharp.codeplex.com/documentation) – Karthik Chintala Dec 18 '12 at 04:51
  • try [Downloads](http://sevenzipsharp.codeplex.com/releases/view/51254) tab, there's the documentation link. – Alireza Dec 18 '12 at 11:20