By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,081 Members | 1,325 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,081 IT Pros & Developers. It's quick & easy.

Uploading Multipart Data to ImageVenue Using C# .NET

P: 6
Okay, I have a problem that has been stumping me for weeks. I have tried many different solutions and this is pretty much my last resort. I have seen a lot of good answers give here so I figured I would give it a try.

First of all, I am using Visual Studio 2005 to write my program. I am using C# .NET as the language. I am running Windows XP Professional with all service packs and updates applied.

Now, I have been trying to write a program that batch uploads pictures to the image hosting service ImageVenue, http://www.imagevenue.com (On a side note, I have tried also with ImageShack but also had the same results). I can't seem to get it right because ImageVenue never returns the linking code to the image. I will post my code as well as some other stuff I have grabbed along the way in hopes that somebody can pick out my error. The code I have written has mostly been borrowed from the web but I have also added to it. I am using a class called MultipartFileUpload to do the uploading and I have written a sort of "driver" program to test the class. I will post the MultipartFileUpload code first.

Here is the code for MultipartFileUpload:

Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Collections.Specialized;
  5. using System.Net;
  6. using System.IO;
  7.  
  8. namespace IVUp
  9. {
  10.     public class MultipartFileUpload
  11.     {
  12.         private Uri uri = null;
  13.         private NameValueCollection parameters = null;
  14.         private NameValueCollection formData = null;
  15.         private String fileDisplayName = null;
  16.         private String fileParameterName = null;
  17.         private FileInfo file = null;
  18.         private NetworkCredential networkCredential = null;
  19.         private String boundary = null;
  20.         private readonly int BUFFER_SIZE = 500;
  21.  
  22.         #region constructors
  23.  
  24.         public MultipartFileUpload()
  25.         {
  26.             parameters = new NameValueCollection();
  27.             formData = new NameValueCollection();
  28.  
  29.             //the boundary signals the we server to look for a new form value or data segment
  30.             boundary = "----------" + DateTime.Now.Ticks.ToString("x");
  31.         }
  32.  
  33.         public MultipartFileUpload(Uri uri) : this()
  34.         {
  35.             this.uri = uri;
  36.         }
  37.  
  38.         #endregion
  39.  
  40.         #region getters and setters
  41.  
  42.         /// <summary>
  43.         /// the destination of the multipart file upload
  44.         /// </summary>
  45.  
  46.         public Uri Uri
  47.         {
  48.             get { return this.uri; }
  49.  
  50.             set { this.uri = value; }
  51.         }
  52.  
  53.         /// <summary>
  54.         /// the parameters to be passed along with the post method  optional
  55.         /// </summary>
  56.  
  57.         public NameValueCollection Parameters
  58.         {
  59.             get { return this.parameters; }
  60.  
  61.             set { this.parameters = value; }
  62.         }
  63.  
  64.         /// <summary>
  65.         /// any form data associated with the post method
  66.         /// </summary>
  67.  
  68.         public NameValueCollection FormData
  69.         {
  70.             get { return this.formData; }
  71.  
  72.             set { this.formData = value; }
  73.         }
  74.  
  75.         /// <summary>
  76.         /// if your web server requires credentials to upload a file, set them here  optional
  77.         /// </summary>
  78.  
  79.         public NetworkCredential NetworkCredential
  80.         {
  81.             get { return this.networkCredential; }
  82.  
  83.             set { this.networkCredential = value; }
  84.         }
  85.  
  86.         #endregion
  87.  
  88.         #region public methods
  89.  
  90.         /// <summary>
  91.         /// adds a parameter to the request, if the parameter already has a value,
  92.         /// it will be overwritten
  93.         /// </summary>
  94.  
  95.         /// <param name="name">name of the parameter</param>
  96.         /// <param name="value">value of the parameter</param>
  97.  
  98.         public void AddParameter(String name, String value)
  99.         {
  100.             if (this.parameters == null)
  101.             {
  102.                 this.parameters = new NameValueCollection();
  103.             }
  104.             this.parameters.Set(name, value);
  105.         }
  106.  
  107.         /// <summary>
  108.         /// adds a form value to the request, if the form field already exists, overwrite it
  109.         /// </summary>
  110.  
  111.         /// <param name="name">the name of the form field</param>
  112.         /// <param name="value">value of the form field</param>
  113.  
  114.         public void AddFormValue(String name, String value)
  115.         {
  116.             if (this.formData == null)
  117.             {
  118.                 this.formData = new NameValueCollection();
  119.             }
  120.             this.parameters.Set(name, value);
  121.         }
  122.  
  123.         /// <summary>
  124.         /// attach a file to the post method, the parameter name and file can not be null
  125.         /// </summary>
  126.  
  127.         /// <param name="fileDisplayName">the name of the file as it should appear to the web server</param>
  128.         /// <param name="parameterName">the parameter that your web server expects to be associated with a file</param>
  129.         /// <param name="file">the actual file you want to upload</param>
  130.         /// <exception cref="ArgumentNullException">file can not be null, name of the parameter cant be null</exception>
  131.  
  132.         public void AttachFile(String fileDisplayName, String parameterName, FileInfo file)
  133.         {
  134.             if(file == null)
  135.             {
  136.                 throw new ArgumentNullException("file", "You must pass a reference to a file");
  137.             }
  138.             if (parameterName == null)
  139.             {
  140.                 throw new ArgumentNullException("parameterName", "You must provide the name of the file parameter.");
  141.             }
  142.             this.file = file;
  143.             if (this.fileDisplayName == null)
  144.             {
  145.                 this.fileDisplayName = file.Name;
  146.             }
  147.         }
  148.  
  149.         /// <summary>
  150.         /// performs the actual upload
  151.         /// </summary>
  152.         /// <returns>the response as a string</returns>
  153.  
  154.         public String UploadFileEx()
  155.         {
  156.             //tack on any parameters or just give us back the uri if there are no parameters
  157.             Uri targetUri = CreateUriWithParameters();
  158.             HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(targetUri);
  159.             webrequest.Credentials = networkCredential; //fine if its null
  160.             webrequest.ContentType = "multipart/form-data; boundary=" + boundary;
  161.             webrequest.Method = "POST";
  162.  
  163.             //encode header
  164.             String postHeader = CreatePostDataString();
  165.             byte[] postHeaderBytes = Encoding.UTF8.GetBytes(postHeader);
  166.             byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n" + boundary + "\r\n");
  167.  
  168.             //read in the file as a stream
  169.             FileStream fileStream = file.Open(FileMode.Open, FileAccess.Read);
  170.             long length = postHeaderBytes.Length + fileStream.Length +boundaryBytes.Length;
  171.  
  172.             //the request method needs to know how big the file is before we start the upload
  173.             webrequest.ContentLength = length;
  174.             Stream requestStream = webrequest.GetRequestStream();
  175.  
  176.             // Write out our post header
  177.             requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
  178.  
  179.             // Write out the file contents
  180.             byte[] buffer = new byte[BUFFER_SIZE];
  181.             int bytesRead = 0;
  182.             while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
  183.             {
  184.                 requestStream.Write(buffer, 0, bytesRead);
  185.             }
  186.  
  187.             // Write out the trailing boundary
  188.             requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
  189.             WebResponse response = webrequest.GetResponse();
  190.             StreamReader sr = new StreamReader(response.GetResponseStream());
  191.             return sr.ReadToEnd(); //response body
  192.         }
  193.  
  194.         #endregion
  195.  
  196.         #region private methods
  197.  
  198.         /// <summary>
  199.         /// helper method to tack on parameters to the request
  200.         /// </summary>
  201.         /// <returns>Uri with parameters, or the original uri if its null</returns>
  202.  
  203.         private Uri CreateUriWithParameters()
  204.         {
  205.             if (uri == null) return null;
  206.             if (parameters == null || parameters.Count <= 0)
  207.             {
  208.                 return this.uri;
  209.             }
  210.  
  211.             String paramString = "?";
  212.             foreach (String key in parameters.Keys)
  213.             {
  214.                 paramString += key + "=" + parameters.Get(key)+"&";
  215.             }
  216.  
  217.             paramString = paramString.Substring(0, paramString.Length - 1); //strip off last &
  218.             return new Uri(uri.ToString() + paramString);
  219.         }
  220.  
  221.         /// <summary>
  222.         /// post data as a string with the boundaries
  223.         /// </summary>
  224.  
  225.         /// <returns>a string representing the form data</returns>
  226.  
  227.         private String CreatePostDataString()
  228.         {
  229.             StringBuilder sb = new StringBuilder();
  230.             for (int i = 0; i < formData.Count; i++)
  231.             {
  232.                 sb.Append("" + boundary + "\r\n");
  233.                 sb.Append("Content-Disposition: form-data; name=\"");
  234.                 sb.Append(formData.GetKey(i) + "\"\r\n\r\n" + formData.Get(i) + "\r\n");
  235.             }
  236.  
  237.             sb.Append("" + boundary + "\r\n");
  238.             sb.Append("Content-Disposition: form-data; name=\"" + fileParameterName + "\";");
  239.             sb.Append("filename=\"" + fileDisplayName + "\" Content-Type: application/octet-stream\r\n\r\n");
  240.             return sb.ToString();
  241.         }
  242.  
  243.         #endregion
  244.     }
  245. }
  246.  
Here is what I have done for the testing part:

Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;
  8. using System.IO;
  9.  
  10. namespace IVUp
  11. {
  12.     public partial class Form1 : Form
  13.     {
  14.         public Form1()
  15.         {
  16.             InitializeComponent();
  17.         }
  18.  
  19.         private void button1_Click(object sender, EventArgs e)
  20.         {
  21.             //MultipartFileUpload Class Code
  22.  
  23.             String UploadResults = "";
  24.             MultipartFileUpload MyMultipart = new MultipartFileUpload();
  25.  
  26.             Uri MyUri = new Uri("http://imagevenue.com/upload.php");
  27.  
  28.             MyMultipart.Uri = MyUri;
  29.             openFileDialog1.ShowDialog();
  30.             FileInfo MyFile = new FileInfo(openFileDialog1.FileName);
  31.             //MyMultipart.AddFormValue("hostval", "10");
  32.             MyMultipart.AttachFile("Test.jpg", "userfile[]", MyFile);
  33.             //MyMultipart.AddFormValue("userfile[]", "C:\\Test.jpg");
  34.             MyMultipart.AddFormValue("imgcontent", "notsafe");
  35.             MyMultipart.AddFormValue("MAX_FILE_SIZE", "");
  36.             MyMultipart.AddFormValue("action", "1");
  37.             MyMultipart.AddFormValue("img_resize", "");
  38.  
  39.             UploadResults = MyMultipart.UploadFileEx();
  40.  
  41.             richTextBox1.Text = UploadResults;
  42.         }
  43.     }
  44. }
  45.  
I have been using Ethereal to capture packets to see if something is wrong with the http part of the stuff. Here is what a standard upload from firefox looks like:

POST /upload.php HTTP/1.1
Host: imagevenue.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.5) Gecko/20070713 ImageShackToolbar/4.2.1 Firefox/2.0.0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://imagevenue.com/host.php
Cookie: __utmz=122915731.1183006481.1.1.utmccn=(direct)|ut mcsr=(direct)|utmcmd=(none); pval=1185169867; __utma=122915731.858623389.1183006481.1183006481.1 186080644.2; __utmc=122915731


And here is what the stuff from my program has looked like so far:

POST /upload.php?imgcontent=notsafe&MAX_FILE_SIZE=&actio n=1&img_resize= HTTP/1.1
Content-Type: multipart/form-data; boundary=----------8c9a331c0cc2e10
Host: imagevenue.com
Content-Length: 12888
Expect: 100-continue
Connection: Keep-Alive


Any help on this would be greatly appreciated. Thanks.
Aug 2 '07 #1
Share this Question
Share on Google+
1 Reply


P: 6
If nobody knows the answer to that question, how about this one: Is the whole WebRequest, HTTPWebRequest, etc. part of Visual Studio just broken when you do form things? I have had several other tasks to perform with forms that also do not work in C# I had been using PHP and CURL to do all these things and I wanted to move to a desktop environment. PHP and CURL made things with forms and HTTP very easy. Apparently C# and .NET do not.
Aug 10 '07 #2

Post your reply

Sign in to post your reply or Sign up for a free account.