locked
Create post files array with WebClient RRS feed

  • Question

  • I finally figured out why my web client wasn't working in debug mode (can't cross ports either).  Now I have it posting a file (or so I think) to my server but I'm not planning to use .NET to receive the file on the back end.

    I've tried looping over the $_FILES array in PHP to determine the name of the key as I can't specify this in my OpenWriteAsync method and alas...there is not one.  This means either one of two things is happening and I think it's the latter:

    1) my code isn't actually uploading a file
    or
    2) using this method doesn't create a $_FILES array.

    Assuming it's #2, is there a way to force this?  I do know that the code below is hitting the page because I can save off the $_GET['folder'] and it's saving with the correct value.

    TIA,

    Burr

     

            private void Upload_Click(object sender, RoutedEventArgs e)
            {
                UriBuilder ub = new UriBuilder("http://localhost/fileupload.php");
                ub.Query = string.Format("folder={0}", "foldertest");
                currentFileInfoIndex = 0;
                WebClient c = new WebClient();
                c.OpenWriteCompleted += new OpenWriteCompletedEventHandler(c_OpenWriteCompleted);
                c.OpenWriteAsync(ub.Uri, "POST");
    
            }
            void c_OpenWriteCompleted(object sender, OpenWriteCompletedEventArgs e)
            {
                FileInfo fileInfo = files[currentFileInfoIndex];
                FileStream fileStream = fileInfo.OpenRead();
                byte[] buffer = new byte[4096];
                int offset = 0;
                int bytesRead = fileStream.Read(buffer, 0, 4096);
                while (bytesRead > 0)
                {
                    offset += bytesRead;
                    //uploadProgress.ShowProgress(offset, total)
                    e.Result.Write(buffer, 0, bytesRead);
                    bytesRead = fileStream.Read(buffer, 0, 4096);
                }
                e.Result.Close();
                fileStream.Close();
                currentFileInfoIndex++;
    
                if (currentFileInfoIndex < files.Count)
                {
                    UriBuilder ub = new UriBuilder("http://localhost/fileupload.php");
                    ub.Query = string.Format("folder={0}", "foldertest");
                    WebClient c = new WebClient();
                    c.OpenWriteCompleted += c_OpenWriteCompleted;
                    c.OpenWriteAsync(ub.Uri, "POST");
                }   
            }    
      
    Wednesday, November 12, 2008 7:59 PM

All replies

  • 2) using this method doesn't create a $_FILES array.

    I'm not a PHP expert, but why would there be a $_FILES array? The files are being uploaded one file at a time so I would only expect a $_POST["fileContents"] and $_POST["fileName"] to be populated.

    Is this what you're trying to do in the PHP script?

    BTW - you can post some of the PHP script here...

    Wednesday, November 12, 2008 9:20 PM
  • The $_FILES array is not an array of multiple files, rather a multidimensional array with information about a single file that has been uploaded.

    it looks something like this: $_FILES = Array ( [myFile] => Array ( [name] => Creek.jpg [type] => image/jpeg [tmp_name] => C:\Windows\Temp\phpE311.tmp [error] => 0 [size] => 264409 ) )

    in order to do anything with the uploaded file in PHP like move_uploaded_file() you need to access that array.

    so what I'm doing is trying to determine the value for the first key on the first dimension of the array (myFile in my example above).  I'm doing that using a foreach loop in PHP

    foreach($_FILES as $key=>$val)... 

    Incidentally, I also checked the POST array and nothing's coming through there either using the code I posted above.  I do know that my $_GET var is getting through (as stated above) because I can write that to a db but my $_FILES and $_POST are blank.

    Wednesday, November 12, 2008 9:53 PM
  •  I just tried another method (straight off of the WebClient video tutorial) and nothing shows in the $_POST nor $_FILES array here either:

     

    private void Button_Click(object sender, RoutedEventArgs e)
            {
                
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Multiselect = true;
                ofd.Filter = "JPEG Images|*.jpg";
                if ((bool)ofd.ShowDialog())
                {
                    btnUpload.Visibility = Visibility.Visible;
                    dgMain.Visibility = Visibility.Visible;
    
                    UploadFile(ofd.File.Name, ofd.File.OpenRead());
    
                    
                }
            }
            
            private void UploadFile(string fileName, FileStream data)
            {
                
                UriBuilder ub = new UriBuilder("http://localhost/fileupload.php");
                ub.Query = string.Format("folder={0}", fileName);
                WebClient c = new WebClient();
                c.OpenWriteCompleted += (sender, e) =>
                    {
                        PushData(data, e.Result);
                        e.Result.Close();
                        data.Close();
                    };
                c.OpenWriteAsync(ub.Uri, "POST");
    
            }
    
            private void PushData(FileStream input, Stream output)
            {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = input.Read(buffer, 0, buffer.Length))!=0)
                {
                    output.Write(buffer, 0, bytesRead);
                }
            }
      
    Wednesday, November 12, 2008 10:33 PM
  • Well I spent some time trying to understand how to make this work using plain ASP.Net and it is pretty complicated. :)

    In the process I found this great project called SilverlightFileUpld on CodePlex which is a great starting point for this stuff. The project uses PHP but you'd probably be better off doing a translation than trying to figure this out from scratch.

    I know you're trying to learn this stuff, but there doesn't seem to be much documentation on it and in this case I think this project is a great tool to learn.

    Good luck!

    Wednesday, November 12, 2008 10:44 PM
  • ya I found that before I started this project and have looked it over some.  TBH, I get a bit lost in his code though.

    Is there another method I can try to upload files aside from the WebClient object?

    I know of httpwebrequest...but I think that WebClient actually uses that so it'd probably put me in the same boat. 

    Wednesday, November 12, 2008 11:12 PM
  • Hi, I was having the same problem, a research on google led me to this forum. I tried to have a look at SilverlightFileUpload and it led me to the solution for my problem. I used Wireshark (a network protocol analyzer/sniffer) to monitor a file upload to a php page using regular HTML/PHP forms and the file upload HTML field. The result is that on a HTTP protocol level there are some parameters defined (not just headers) that create the $_FILES array on the PHP side of things, it looks something like this: POST /image_upload.php HTTP/1.1 Host: [....] User-Agent: [...] [other regular headers...] Content-Type: multipart/form-data; boundary=--------41134763834 Content-Length: 45866 --------41134763834 Content-Disposition: form-data; name="pic"; filename="[...]" Content-Type: image/png .PNG [... the actual PNG file follows] So it looks like there are some special parameters like that boundary and some extra headers like Content-Disposition and Content-Length. And the PHP reads it and parses it into the $_FILES header. Now, I was about to start developing my own implementation of a HTTP client class to do this when I found out a much easier way to handle it from the PHP side without using the $_FILES variable. All you have to do is to read the content of a special file called "php://input" this gives you direct access to any data being uploaded on the request as if it were a file so what you do is: $input = file_get_contents("php://input"); $file = fopen("upload/output_file_name", "w"); fwrite($file, $input); fclose($file); if you wish to impose file size limit you can check for the $input string size like this if (strlen($input) > 1024) { // 1K file size limit die("output some error"); } simple.... and on the Silverlight side you just write to the WebClient stream as you're doing already, I'm using a code similar to the one showed in that video mentioned above in the thread and it works just fine. I hope that helps...
    Wednesday, February 25, 2009 12:43 PM
  •  very cool.  I've never heard of php://input I'll have to give this a try when I get some time later.

    thanks for the tip!

    Wednesday, March 4, 2009 10:34 AM
  • Hi evereybody.

    Very nice Cyber. You've solved my problem.

    Thank you ;)

    Tuesday, January 18, 2011 6:04 AM
  • I'm new at this stuff..

    So I was wondering, is it then possible to fill the $_FILES variable from within Silverlight and then call a php page to upload a file?

    The reason I'm asking is because I would like to have a file uploaded to a server using PHP, but the "popup" to allow the user to load the file will occur in Silverlight and not in PHP.

     

    Monday, January 23, 2012 10:03 AM
  • So in the end, I decided to simply deal with user-initiated input, and with that I will use Plupload. Works like a charm!

    Tuesday, January 31, 2012 3:42 PM