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.
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.
Comment