Uploading Multipart Data to ImageVenue Using C# .NET

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • WeCi2i
    New Member
    • Aug 2007
    • 6

    Uploading Multipart Data to ImageVenue Using C# .NET

    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 MultipartFileUp load to do the uploading and I have written a sort of "driver" program to test the class. I will post the MultipartFileUp load code first.

    Here is the code for MultipartFileUp load:

    [code=c]
    using System;
    using System.Collecti ons.Generic;
    using System.Text;
    using System.Collecti ons.Specialized ;
    using System.Net;
    using System.IO;

    namespace IVUp
    {
    public class MultipartFileUp load
    {
    private Uri uri = null;
    private NameValueCollec tion parameters = null;
    private NameValueCollec tion formData = null;
    private String fileDisplayName = null;
    private String fileParameterNa me = null;
    private FileInfo file = null;
    private NetworkCredenti al networkCredenti al = null;
    private String boundary = null;
    private readonly int BUFFER_SIZE = 500;

    #region constructors

    public MultipartFileUp load()
    {
    parameters = new NameValueCollec tion();
    formData = new NameValueCollec tion();

    //the boundary signals the we server to look for a new form value or data segment
    boundary = "----------" + DateTime.Now.Ti cks.ToString("x ");
    }

    public MultipartFileUp load(Uri uri) : this()
    {
    this.uri = uri;
    }

    #endregion

    #region getters and setters

    /// <summary>
    /// the destination of the multipart file upload
    /// </summary>

    public Uri Uri
    {
    get { return this.uri; }

    set { this.uri = value; }
    }

    /// <summary>
    /// the parameters to be passed along with the post method — optional
    /// </summary>

    public NameValueCollec tion Parameters
    {
    get { return this.parameters ; }

    set { this.parameters = value; }
    }

    /// <summary>
    /// any form data associated with the post method
    /// </summary>

    public NameValueCollec tion FormData
    {
    get { return this.formData; }

    set { this.formData = value; }
    }

    /// <summary>
    /// if your web server requires credentials to upload a file, set them here — optional
    /// </summary>

    public NetworkCredenti al NetworkCredenti al
    {
    get { return this.networkCre dential; }

    set { this.networkCre dential = value; }
    }

    #endregion

    #region public methods

    /// <summary>
    /// adds a parameter to the request, if the parameter already has a value,
    /// it will be overwritten
    /// </summary>

    /// <param name="name">nam e of the parameter</param>
    /// <param name="value">va lue of the parameter</param>

    public void AddParameter(St ring name, String value)
    {
    if (this.parameter s == null)
    {
    this.parameters = new NameValueCollec tion();
    }
    this.parameters .Set(name, value);
    }

    /// <summary>
    /// adds a form value to the request, if the form field already exists, overwrite it
    /// </summary>

    /// <param name="name">the name of the form field</param>
    /// <param name="value">va lue of the form field</param>

    public void AddFormValue(St ring name, String value)
    {
    if (this.formData == null)
    {
    this.formData = new NameValueCollec tion();
    }
    this.parameters .Set(name, value);
    }

    /// <summary>
    /// attach a file to the post method, the parameter name and file can not be null
    /// </summary>

    /// <param name="fileDispl ayName">the name of the file as it should appear to the web server</param>
    /// <param name="parameter Name">the parameter that your web server expects to be associated with a file</param>
    /// <param name="file">the actual file you want to upload</param>
    /// <exception cref="ArgumentN ullException">f ile can not be null, name of the parameter can’t be null</exception>

    public void AttachFile(Stri ng fileDisplayName , String parameterName, FileInfo file)
    {
    if(file == null)
    {
    throw new ArgumentNullExc eption("file", "You must pass a reference to a file");
    }
    if (parameterName == null)
    {
    throw new ArgumentNullExc eption("paramet erName", "You must provide the name of the file parameter.");
    }
    this.file = file;
    if (this.fileDispl ayName == null)
    {
    this.fileDispla yName = file.Name;
    }
    }

    /// <summary>
    /// performs the actual upload
    /// </summary>
    /// <returns>the response as a string</returns>

    public String UploadFileEx()
    {
    //tack on any parameters or just give us back the uri if there are no parameters
    Uri targetUri = CreateUriWithPa rameters();
    HttpWebRequest webrequest = (HttpWebRequest )WebRequest.Cre ate(targetUri);
    webrequest.Cred entials = networkCredenti al; //fine if it’s null
    webrequest.Cont entType = "multipart/form-data; boundary=" + boundary;
    webrequest.Meth od = "POST";

    //encode header
    String postHeader = CreatePostDataS tring();
    byte[] postHeaderBytes = Encoding.UTF8.G etBytes(postHea der);
    byte[] boundaryBytes = Encoding.ASCII. GetBytes("\r\n– " + boundary + "\r\n");

    //read in the file as a stream
    FileStream fileStream = file.Open(FileM ode.Open, FileAccess.Read );
    long length = postHeaderBytes .Length + fileStream.Leng th +boundaryBytes. Length;

    //the request method needs to know how big the file is before we start the upload
    webrequest.Cont entLength = length;
    Stream requestStream = webrequest.GetR equestStream();

    // Write out our post header
    requestStream.W rite(postHeader Bytes, 0, postHeaderBytes .Length);

    // Write out the file contents
    byte[] buffer = new byte[BUFFER_SIZE];
    int bytesRead = 0;
    while ((bytesRead = fileStream.Read (buffer, 0, buffer.Length)) != 0)
    {
    requestStream.W rite(buffer, 0, bytesRead);
    }

    // Write out the trailing boundary
    requestStream.W rite(boundaryBy tes, 0, boundaryBytes.L ength);
    WebResponse response = webrequest.GetR esponse();
    StreamReader sr = new StreamReader(re sponse.GetRespo nseStream());
    return sr.ReadToEnd(); //response body
    }

    #endregion

    #region private methods

    /// <summary>
    /// helper method to tack on parameters to the request
    /// </summary>
    /// <returns>Uri with parameters, or the original uri if it’s null</returns>

    private Uri CreateUriWithPa rameters()
    {
    if (uri == null) return null;
    if (parameters == null || parameters.Coun t <= 0)
    {
    return this.uri;
    }

    String paramString = "?";
    foreach (String key in parameters.Keys )
    {
    paramString += key + "=" + parameters.Get( key)+"&";
    }

    paramString = paramString.Sub string(0, paramString.Len gth - 1); //strip off last &
    return new Uri(uri.ToStrin g() + paramString);
    }

    /// <summary>
    /// post data as a string with the boundaries
    /// </summary>

    /// <returns>a string representing the form data</returns>

    private String CreatePostDataS tring()
    {
    StringBuilder sb = new StringBuilder() ;
    for (int i = 0; i < formData.Count; i++)
    {
    sb.Append("–" + boundary + "\r\n");
    sb.Append("Cont ent-Disposition: form-data; name=\"");
    sb.Append(formD ata.GetKey(i) + "\"\r\n\r\n " + formData.Get(i) + "\r\n");
    }

    sb.Append("–" + boundary + "\r\n");
    sb.Append("Cont ent-Disposition: form-data; name=\"" + fileParameterNa me + "\";");
    sb.Append("file name=\"" + fileDisplayName + "\" Content-Type: application/octet-stream\r\n\r\n" );
    return sb.ToString();
    }

    #endregion
    }
    }
    [/code]

    Here is what I have done for the testing part:

    [code=c]
    using System;
    using System.Collecti ons.Generic;
    using System.Componen tModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows. Forms;
    using System.IO;

    namespace IVUp
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeCompo nent();
    }

    private void button1_Click(o bject sender, EventArgs e)
    {
    //MultipartFileUp load Class Code

    String UploadResults = "";
    MultipartFileUp load MyMultipart = new MultipartFileUp load();

    Uri MyUri = new Uri("http://imagevenue.com/upload.php");

    MyMultipart.Uri = MyUri;
    openFileDialog1 .ShowDialog();
    FileInfo MyFile = new FileInfo(openFi leDialog1.FileN ame);
    //MyMultipart.Add FormValue("host val", "10");
    MyMultipart.Att achFile("Test.j pg", "userfile[]", MyFile);
    //MyMultipart.Add FormValue("user file[]", "C:\\Test.jpg") ;
    MyMultipart.Add FormValue("imgc ontent", "notsafe");
    MyMultipart.Add FormValue("MAX_ FILE_SIZE", "");
    MyMultipart.Add FormValue("acti on", "1");
    MyMultipart.Add FormValue("img_ resize", "");

    UploadResults = MyMultipart.Upl oadFileEx();

    richTextBox1.Te xt = UploadResults;
    }
    }
    }
    [/code]

    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 ImageShackToolb ar/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,ima ge/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=12291573 1.1183006481.1. 1.utmccn=(direc t)|utmcsr=(dire ct)|utmcmd=(non e); pval=1185169867 ; __utma=12291573 1.858623389.118 3006481.1183006 481.1186080644. 2; __utmc=12291573 1


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

    POST /upload.php?imgc ontent=notsafe& MAX_FILE_SIZE=& action=1&img_re size= 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.
  • WeCi2i
    New Member
    • Aug 2007
    • 6

    #2
    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.

    Comment

    Working...