none
Background Transfer Service Upload Problem RRS feed

  • General discussion

  • Hi all,

    I'm trying to develop a windows phone 7 app for personal use where I can upload images and audio files from my phone to a public server. Due to the nature of my phone use, I'm wanting to select a file to upload and have it upload in the background, so I thought that using the Background Transfer Service would be the best option. Because of the chosen method, I'm trying to upload the file to a PHP script, and while the BackgroundTransferRequest states its sending data, the file doesn't seem to be uploading. I don't know what I'm doing wrong, and not sure if it can be linked to the post request file the BackgroundTransferService is generating. Below I have included the code I feel you might need in order to help me.

    1 public static void SetFile(Stream fileToUpload, FileType fileType) 
    2         { 
    3             if (fileToUpload == null || fileToUpload.Length == 0) 
    4             { 
    5                 throw new ArgumentException("FileToUpload can not be equal to null or empty"); 
    6             } 
    7             else if (fileType != FileType.Audio && fileType != FileType.Image) 
    8             { 
    9                 throw new ArgumentException("Only images and sound bites can be uploaded"); 
    10             } 
    11  
    12             BlauploadUploader.FileToUpload = fileToUpload; 
    13             BlauploadUploader.FileType = fileType; 
    14         } 
    15  
    16         public static void UploadFile(string filename) 
    17         { 
    18             try 
    19             { 
    20                 if (BlauploadUploader.FileToUpload == null
    21                 { 
    22                     throw new InvalidOperationException("File to upload must be set"); 
    23                 } 
    24                 else if (String.IsNullOrEmpty(filename)) 
    25                 { 
    26                     throw new ArgumentException("Filename must be provided"); 
    27                 } 
    28  
    29                 if (FileType == blueroom.FileType.Image) 
    30                 { 
    31                     using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication()) 
    32                     { 
    33                         if (storage.FileExists(@"shared/transfers/" + filename)) 
    34                         { 
    35                             MessageBox.Show(String.Format("A file with the name '{0}' is currently in the process of being transfered. Please choose a different name"
    36                                                           filename), 
    37                                             "File with that name already exists"
    38                                             MessageBoxButton.OK); 
    39                             return
    40                         } 
    41  
    42                         using (IsolatedStorageFileStream stream = storage.CreateFile(@"shared/transfers/" + filename)) 
    43                         { 
    44                             BitmapImage image = new BitmapImage(); 
    45                             image.SetSource(FileToUpload); 
    46                             WriteableBitmap wb = new WriteableBitmap(image); 
    47  
    48                             wb.SaveJpeg(stream, wb.PixelWidth, wb.PixelHeight, 0, 100); 
    49                         } 
    50                     } 
    51                 } 
    52  
    53                 BackgroundTransferRequest request = new BackgroundTransferRequest(new Uri(BlauploadUploader.UploadAddress, UriKind.Absolute)); 
    54                 request.UploadLocation = new Uri(@"shared/transfers/" + filename, UriKind.Relative); 
    55                 request.Method = "POST"
    56                 BackgroundTransferManager.AddTransferRequest(request); 
    57             } 
    58             catch (Exception ex) 
    59             { 
    60                 MessageBox.Show(ex.Message, "Whoops!", MessageBoxButton.OK); 
    61             } 
    62         }

    1 /// <summary> 
    2         /// Add a transfer request to the BackgroundTransferService. If the service is currently full 
    3         /// up, then it will be added to the pending collection where it will be added once a space becomes 
    4         /// available 
    5         /// </summary> 
    6         /// <param name="request">The request to add</param> 
    7         public static void AddTransferRequest(BackgroundTransferRequest request) 
    8         { 
    9             if (request == null
    10             { 
    11                 throw new System.ArgumentNullException("BackgroundTransferRequest was equal to null"); 
    12             } 
    13  
    14             // If the BackgroundTransferService isn't full, add the request straight to the service, otherwise 
    15             // add it to the pending background requests collection 
    16             if (BackgroundTransferManager.ActiveTransferCount < ActiveTransferLimit) 
    17             { 
    18                 request.TransferStatusChanged += BackgroundTransferManager.RequestStatusChanged; 
    19  
    20                 BackgroundTransferManager.ActiveTransferCount++; 
    21                 BackgroundTransferService.Add(request); 
    22             } 
    23             else 
    24             { 
    25                 _PendingBackgroundRequests.Add(request); 
    26             } 
    27         } 

    Sunday, October 16, 2011 6:38 PM

All replies

  • The best way to debug it is probably something like Fiddler. http://blogs.msdn.com/b/fiddler/archive/2011/01/09/debugging-windows-phone-7-device-traffic-with-fiddler.aspx provides good instructions on how to set it up to capture data. I found that I needed to specify the dev PC's local IP (the one that'll likely look like 192.168.X.Y) rather than its name and that I needed to run the program while my phone was detached from the computer.

    I expected that it would be sending the file content as some sort of multi-part submission (same as a form on a webpage) but it's just the HEADER stuff (POST, etc.) followed directly by the file's contents. I wound up sticking the file's name into the Request's headers as a custom header and then using the data itself as a stream along with a BinaryWriter to write it out. I'll post the server side code, but it's for ASP.NET MVC3 so I doubt it'd be much use.

            [HttpPost]  
            public ActionResult SomeControllerMethod(string fileName)  
            {  
                // I used "File-Name" as the custom header key for the filename.  
                fileName = this.Request.Headers["File-Name"];  
     
                if (String.IsNullOrEmpty(fileName))  
                {  
                    // You likely want to replace this with something more graceful  
                    // for production use, e.g. an HTTP 400 response or something  
                    // otherwise indicating a header problem.  
                    throw new ArgumentException("Filename is: " + (fileName ?? "(null)") + ".""fileName");  
                }  
     
                // You probably want to include a check on the Content-Length  
                // and maybe a few other checks too, just to be safe (assuming  
                // your server isn't otherwise configured to block huge requests).  
     
                // Save to somewhere in App_Data to avoid public exposure of contents  
                // outside of some approved mechanism for accessing them.  
                var path = Path.Combine(Server.MapPath("~/App_Data/SomeDir"), fileName);  
                if (!Directory.Exists(Server.MapPath("~/App_Data/SomeDir")))  
                {  
                    Directory.CreateDirectory(Server.MapPath("~/App_Data/SomeDir"));  
                }  
     
                using (var stream = System.IO.File.Open(path, FileMode.Create))  
                {  
                    using (var writer = new BinaryWriter(stream))  
                    {  
                        byte[] data = new byte[this.Request.InputStream.Length];  
                        this.Request.InputStream.Read(data, 0, data.Length);  
                        writer.Write(data);  
                    }  
                }  
     
                // Redirects to a parameter-less "GET" Index that redirects to some  
                // other valid page (needed since it expects either a 200 or a 206 back  
                // in order to complete.  
                return RedirectToAction("Index");  
            }  
     
     

    I commented that some to point out some potential issues that it doesn't address. The code itself was just a test to get something working for an app that's not yet ready to do real uploading yet, so parameter check safeguards, some sort of authentication mechanism, etc., aren't in place.
    Sunday, October 16, 2011 7:13 PM