<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>file-upload &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/file-upload/</link>
	<description>Feed of posts on WordPress.com tagged "file-upload"</description>
	<pubDate>Sat, 26 Dec 2009 23:45:56 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Dear Browser Makers: Please fix &lt;input type=&rdquo;file&rdquo; /&gt;]]></title>
<link>http://dpaoliello.wordpress.com/2009/12/17/dear-browser-makers-please-fix-input-typefile/</link>
<pubDate>Thu, 17 Dec 2009 15:52:57 +0000</pubDate>
<dc:creator>tehpenguin</dc:creator>
<guid>http://dpaoliello.wordpress.com/2009/12/17/dear-browser-makers-please-fix-input-typefile/</guid>
<description><![CDATA[tldr: Browsers need better ways of handling large HTTP requests &#8211; possibly with an &quot;uploa]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>tldr: Browsers need better ways of handling large HTTP requests &#8211; possibly with an &#34;upload monitor&#34; (Scroll to the last paragraph for a little more)</p>
<p>I think that we’ve all come across this before: you go to a website, select a file to upload, hit “Submit” and then wait forever and hope that the file you’ve selected has actually made it to the server on the other side. Recently, while building an <a href="http://www.asp.net/mvc" target="_blank">ASP.NET MVC</a> application for a client, I decided that I wanted a better experience for my end users, especially since this application is to be externally hosted from the client, who is the primary user. As such, I didn’t want the client to be waiting and hoping that the documents and images that they are uploading are actually reaching the other side.</p>
<p>So, to get past this issue, my first idea was to turn to AJAX. Using JavaScript made sense as it meant that no 3rd-party plugins are required and that anyone with JavaScript disabled can still upload files (albeit with a worse interface &#8211; but anyone disabling JavaScript should expect that). Unfortunately, AJAX file uploaders appeared to be mediocre at best &#8211; they were inaccurate with percentage (if they showed a percentage), the interfaces were pretty poor and most didn&#8217;t support multiple file upload features (such as selecting multiple files in the open file dialog).</p>
<p>With a quick bit of searching, I found <a href="http://swfupload.org/" target="_blank">SWFUpload</a> &#8211; which appeared to have all the features that I wanted: a nice interface, multiple file uploads and very customisable. Having implemented SWFUpload into my application, I hit a major bug. As it turns out, SWFUpload was built using Flash, and Flash (being the wonderful Adobe application it is) only sends cookies from Internet Explorer, if at all. This meant that the uploading component would not use the same session as Firefox, and so would be redirected to the &#34;log in&#34; page instead of uploading the file. <a href="http://www.swfupload.org/forum/generaldiscussion/98" target="_blank">The suggested fix from SWFUpload</a> didn&#8217;t work (apart from the various security exploits it introduced) and implementing my own <a href="http://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionidmanager.aspx" target="_blank">SessionIDManager</a> (to permit session id&#8217;s in the query string) failed due to ASP.NET&#8217;s SQL Membership Provider storing additional Authentication data in a separate cookie.</p>
<p>Luckily enough, <a href="http://www.silverlightshow.net/items/Cookies-in-Silverlight-Web-Requests.aspx" target="_blank">Silverlight supports sending the cookies from the browser it is hosted in</a>. Hoping for a simple, drop-in solution I was (again) severely disappointed. The Silverlight component I had chosen (<a href="http://slfileupload.codeplex.com/" target="_blank">Silverlight Multi File Uploader</a>), <a href="http://www.codeplex.com/SilverlightFileUpld" target="_blank">as well as many others</a>, send the file in the body of the HTTP request (instead of putting it in a mulitpart/form-data encoded POST header) and chunked the upload. This was greatly frustrating as I wanted to put the uploaded file straight into the database, without placing it temporarily on the file system. After some hacking of the Silverlight component, I was able to strip out the chunking code, but attempting to have the request use mulitpart/form-data failed due to Silverlight&#8217;s unusual (but rather logical) way of doing HTTP Requests. Silverlight relies on the browser sending the request and completing its headers (such as Content-Length). However, the Content-Length header is put before the Content-Type and this causes IIS (and, most likely, every other webserver) to ignore the POST variables. In short, I couldn&#8217;t have the file uploaded properly (ie appearing in the Request.Files array), but I could live with put it in the HTTP Request body (and access it via the Request.InputStream stream).</p>
<p>But enough of the backstory &#8211; what is to be done? Well, its quite simple. The user&#8217;s browser should realise that it is uploading a large file and show the user how much of the file is complete (and, possibly, speed and estimated time). I find it curious that the user is presented so much information about a download and yet next to nothing about the statistics of an upload. When you think about it from a web developer&#8217;s point of view, the browser is the only place to implement this feature. Why? Because HTML is for content, CSS for styling and JavaScript for functionality. Out of those three, JavaScript is the best candidate for implementing an upload &#34;monitor&#34;; but JavaScript has no information about the OS the browser is in (nor should it), and so there is no way for the JavaScript to know how large the file is &#8211; this means that the responsibility falls out of the Web Developer&#8217;s hands and into the browsers hands. </p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[online file upload service]]></title>
<link>http://softsters.wordpress.com/2009/11/18/online-file-upload-service/</link>
<pubDate>Wed, 18 Nov 2009 09:11:37 +0000</pubDate>
<dc:creator>softsters</dc:creator>
<guid>http://softsters.wordpress.com/2009/11/18/online-file-upload-service/</guid>
<description><![CDATA[Sharebee.com, the one and only online file upload distribution service. To help you keep your shared]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a href="http://www.sharebee.com/">Sharebee.com</a>, the one and only online file upload distribution service. To help you keep your shared files online using several different file hosting / web hosting providers.</p>
<p>Upload »<br />
Choose the file you want to keep<br />
online and upload it at Sharebee.<br />
Distribute »<br />
Sharebee will upload the file to<br />
several file hosting services.<br />
Update »<br />
Links are checked for status and will<br />
be removed and updated when needed. </p>
<p>About Sharebee:  Thank you for using Sharebee.com, Sharebee 3.0 final will be released very soon. With many new features!<br />
Ready to upload your file? Upload as much as you want.<br />
Sharebee.com is a 100% free service, sponsored by advertisements.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Java vs Flash File Uploaders]]></title>
<link>http://icewalker2g.wordpress.com/2009/11/13/java-vs-flash-file-uploaders/</link>
<pubDate>Fri, 13 Nov 2009 23:55:33 +0000</pubDate>
<dc:creator>Francis Adu-Gyamfi</dc:creator>
<guid>http://icewalker2g.wordpress.com/2009/11/13/java-vs-flash-file-uploaders/</guid>
<description><![CDATA[I was using my Yahoo mail today and had to spend of most of the day attaching and sending some moder]]></description>
<content:encoded><![CDATA[I was using my Yahoo mail today and had to spend of most of the day attaching and sending some moder]]></content:encoded>
</item>
<item>
<title><![CDATA[Very Interesting! Three new user interface controls in ColdFusion 9]]></title>
<link>http://coldfusionupdate.wordpress.com/2009/11/11/very-interesting-three-new-user-interface-controls-in-coldfusion-9/</link>
<pubDate>Wed, 11 Nov 2009 15:57:47 +0000</pubDate>
<dc:creator>ColdFusionupdate</dc:creator>
<guid>http://coldfusionupdate.wordpress.com/2009/11/11/very-interesting-three-new-user-interface-controls-in-coldfusion-9/</guid>
<description><![CDATA[Check this link for details : Three new user interface controls in ColdFusion 9http://www.adobe.com/]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Check this link for details : <a class="aligncenter" title="Three new user interface controls in ColdFusion 9" href="http://www.adobe.com/devnet/coldfusion/articles/coldfusion9_uicontrols.html">Three new user interface controls in ColdFusion 9</a><a href="http://www.adobe.com/devnet/coldfusion/articles/coldfusion9_uicontrols.html">http://www.adobe.com/devnet/coldfusion/articles/coldfusion9_uicontrols.html</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[PHP File Upload]]></title>
<link>http://sounthar.wordpress.com/2009/11/04/php-file-upload/</link>
<pubDate>Wed, 04 Nov 2009 11:34:57 +0000</pubDate>
<dc:creator>sounthar</dc:creator>
<guid>http://sounthar.wordpress.com/2009/11/04/php-file-upload/</guid>
<description><![CDATA[index.php &lt;html&gt; &lt;body bgcolor=’#909090′&gt;&lt;br/&gt;&lt;br/&gt; &lt;center&gt; &lt;form ]]></description>
<content:encoded><![CDATA[index.php &lt;html&gt; &lt;body bgcolor=’#909090′&gt;&lt;br/&gt;&lt;br/&gt; &lt;center&gt; &lt;form ]]></content:encoded>
</item>
<item>
<title><![CDATA[Upload Multiple Files to Google Docs]]></title>
<link>http://techbays.com/2009/10/29/upload-multiple-files-to-google-docs/</link>
<pubDate>Fri, 30 Oct 2009 01:46:23 +0000</pubDate>
<dc:creator>lemeylou echavez</dc:creator>
<guid>http://techbays.com/2009/10/29/upload-multiple-files-to-google-docs/</guid>
<description><![CDATA[Instead of picking one file at a time, Google Doc&#8217;s new upload page lets you choose multiple f]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Instead of picking one file at a time, Google Doc&#8217;s new <a href="http://docs.google.com/support/bin/answer.py?hl=en&#38;answer=147167">upload page</a> lets you choose multiple files and upload them simultaneously, in just a couple of steps.</p>
<p><strong>Prerequisite</strong>: <a href="http://techbays.com/2009/09/19/create-a-google-account/">Google account</a>.</p>
<p><strong>Application Site</strong>: <a href="http://docs.google.com/">http://docs.google.com/</a></p>
<p><strong>Process Time</strong>: 1 minute.</p>
<p><strong>Steps</strong>:</p>
<p>Step-1. Go to the application site.</p>
<p>Step-2. Log in to your account.</p>
<p>Step-4. Click the &#8220;Upload&#8221; button on the upper left corner of the page.</p>
<p>Step-5. Click<strong> </strong>&#8220;Select files to upload&#8221; to upload files from your computer. [1]</p>
<p>Step-6. The file browser pops up. Select multiple files by pressing Shift and clicking the files.</p>
<p>Step-6. Alternatively, click the &#8220;Select more files&#8221; link that appears after you upload the first set of files if you want to select more files.</p>
<p>Step-7. Select a &#8220;Destination folder&#8221; from your Google Docs. [2]</p>
<p>Step-8. Click &#8220;Start upload&#8221;.</p>
<p>Step-9. Google Docs displays the status of upload per file until completion.</p>
<p><strong>Compare</strong>:  <a title="Upload PDF Files on Google Docs" rel="bookmark" href="http://techbays.com/2009/01/20/upload-pdf-files-on-google-docs/">Upload PDF Files on Google Docs</a></p>
<p><strong>Notes</strong>:</p>
<p>[1] Conversion limitations and supported file types:</p>
<p>Documents (up to 500KB of text)</p>
<ul>
<li>HTML files and plain text (.txt).</li>
<li>Microsoft Word (.doc, .docx), Rich Text (.rtf), OpenDocument Text (.odt) and StarOffice (.sxw).</li>
</ul>
<p>Presentations (up to 10MB)</p>
<ul>
<li>Microsoft PowerPoint (.ppt, .pps).</li>
</ul>
<p>Spreadsheets (up to 1MB)</p>
<ul>
<li>Comma Separated Value (.csv).</li>
<li>Microsoft Excel (.xls, .xlsx) files and OpenDocument Spreadsheet (.ods).</li>
</ul>
<p>PDF Files (up to 10MB)</p>
<p>[2] This is optional. Default is &#8220;No folder&#8221;.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Sharepoint File Upload]]></title>
<link>http://sladescross.wordpress.com/2009/10/05/sharepoint-file-upload/</link>
<pubDate>Mon, 05 Oct 2009 15:43:47 +0000</pubDate>
<dc:creator>sladescross</dc:creator>
<guid>http://sladescross.wordpress.com/2009/10/05/sharepoint-file-upload/</guid>
<description><![CDATA[http://msdn.microsoft.com/en-us/library/dd490727.aspx C# Copy Code //String parameters to assign sit]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a href="http://msdn.microsoft.com/en-us/library/dd490727.aspx">http://msdn.microsoft.com/en-us/library/dd490727.aspx</a></p>
<p>C# Copy Code //String parameters to assign site and document library destination URL<br />
const string siteUrl = &#8220;<a href="http://moss2007rtm1/">http://moss2007rtm1/</a>&#8220;;<br />
const string siteName = &#8220;/SiteDirectory/PartsList/&#8221;;<br />
const string destination = &#8220;<a href="http://moss2007rtm1/SiteDirectory/PartsList/Shared%20Documents/TestUpload.doc">http://moss2007rtm1/SiteDirectory/PartsList/Shared%20Documents/TestUpload.doc</a>&#8220;;</p>
<p>//Freeze UI<br />
Cursor = Cursors.WaitCursor;<br />
buttonNewFolder.Enabled = false;<br />
buttonUploadDocument.Enabled = false;</p>
<p>//Use SPSite class constructor to create site collection based on URL<br />
SPSite siteCollection = new SPSite(siteUrl);</p>
<p>//Assign target web site based on site name<br />
SPWeb site = siteCollection.AllWebs[siteName];</p>
<p>//Assign file stream to file opened based on file location form input<br />
FileStream fStream = File.OpenRead(textBoxFilePath.Text);</p>
<p>//Instantiate byte array to correspond to the file stream object<br />
byte[] contents = new byte[fStream.Length];</p>
<p>//Read data from file stream and write into byte array<br />
fStream.Read(contents, 0, (int)fStream.Length);<br />
fStream.Close();</p>
<p>//Add file to document library based on destination URL and content of byte array<br />
site.Files.Add(destination, contents);</p>
<p>//UI clean-up<br />
Cursor = Cursors.Default;<br />
buttonNewFolder.Enabled = true;<br />
buttonUploadDocument.Enabled = true;</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[File Upload on Google App Engine using struts2]]></title>
<link>http://whyjava.wordpress.com/2009/10/04/file-upload-on-google-app-engine-using-struts2/</link>
<pubDate>Sun, 04 Oct 2009 13:14:02 +0000</pubDate>
<dc:creator>whyjava</dc:creator>
<guid>http://whyjava.wordpress.com/2009/10/04/file-upload-on-google-app-engine-using-struts2/</guid>
<description><![CDATA[Intent of my Blog Few months back, i wrote a blog on Creating Struts2 application on Google App Engi]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><strong>Intent of my Blog</strong></p>
<p>Few months back, i wrote a blog on <a href="http://whyjava.wordpress.com/2009/08/30/creating-struts2-application-on-google-app-engine-gae/">Creating Struts2 application on Google App Engine </a> and some developers asked me how to upload a file using struts2 on google app engine. At that point of time, i was playing with google app engine and was not very clear about the limitation google app engine imposes. Google App Engine does not allow your application to write a file to their application server. This was a very big limitation as most of the application require some sort of file upload. So, i decided to find some way by which i can achieve the upload functionality and i found <a href="http://code.google.com/appengine/kb/java.html#fileforms">this link</a>. But, i didn&#8217;t wanted to use servelt in my code because i was trying to build a application using struts 2.I wanted to work with actions and use <a href="http://struts.apache.org/2.0.14/struts2-core/apidocs/org/apache/struts2/interceptor/FileUploadInterceptor.html">FileUploadInterceptor</a>. With the current implementation of struts 2 FileUploadInterceptor, i can&#8217;t do fileupload because it writes file to server.So, after spending some time with struts2 code, i wrote my own extension for <a href="http://code.google.com/p/struts2-gae/">Struts 2</a>.This post will discuss how you can use small struts2 wrapper framework, i created for google app engine in your application to do fileupload and more.</p>
<p><strong>Prerequisites for starting Struts2 Application on Google App Engine</strong></p>
<p>Before you start building your sample application on google app engine using struts 2 you will need the following:-</p>
<ol>
<li>Google App Engine runs on java 5 and above so if necessary, <a href="http://java.sun.com/javase/downloads/index.jsp">download and install the Java SE Development Kit (JDK) for your platform</a> and <a href="http://developer.apple.com/java/">for mac users</a> download and install the latest version.</li>
<li>In this example we will be using Eclipse as our ide. So if necessary, <a href="http://www.eclipse.org/">download eclipse </a> and <a href="http://code.google.com/appengine/docs/java/tools/eclipse.html">google app engine plugin for eclipse</a>.You will also need to download the <a href="http://code.google.com/appengine/downloads.html">google  java app engine SDK</a>. For more information you can refer to <a href="http://code.google.com/appengine/docs/java/gettingstarted/installing.html">installing the java SDK for google app engine</a>.</li>
<li>Download the latest release of <a href="http://struts.apache.org/download.cgi">Struts2 framework</a>.If you want to learn struts 2 a very good reference is struts 2 in action book.Please buy <a href="http://www.amazon.com/gp/product/193398807X?ie=UTF8&#38;tag=javblo07-20&#38;linkCode=as2&#38;camp=1789&#38;creative=9325&#38;creativeASIN=193398807X">Struts 2 in Action</a><img style="border:medium none!important;margin:0!important;" src="http://www.assoc-amazon.com/e/ir?t=javblo07-20&#38;l=as2&#38;o=1&#38;a=193398807X" border="0" alt="" width="1" height="1" />.</li>
<li>Download the latest release of <a href="http://code.google.com/p/struts2-gae/">struts2-gae framework</a>.It is an wrapper around struts 2 for google app engine.</li>
</ol>
<p><strong>Step by Step procedure to create Struts2 File Upload application on Google App Engine.</strong></p>
<p><strong>Step 1</strong>: Create a new project by clicking the New Web Application Project button in the toolbar<img title="new_app_button" src="http://whyjava.files.wordpress.com/2009/08/new_app_button1.png?w=20&#038;h=20#38;h=20" alt="new_app_button" width="20" height="20" />.</p>
<p><img class="aligncenter size-large wp-image-17" title="1" src="http://whyjava.wordpress.com/files/2009/08/11.jpg?w=1024" alt="1" width="1024" height="624" /></p>
<p><strong>Step 2</strong> : Give the project name say struts2-fileupload  as we are going to create a simple file upload application. Enter package name as com.login and uncheck “Use Google Web Toolkit,” and ensure “Use Google App Engine” is checked and click the finish button.</p>
<p><img class="aligncenter size-large wp-image-108" title="s1" src="http://whyjava.wordpress.com/files/2009/10/s1.jpg?w=1024" alt="s1" width="1024" height="640" /></p>
<p><strong>Step3</strong> : When you click the finish button you will get a sample HelloWorld application, which you can run going in the Run menu, select Run As &#62; Web Application.By default application will run at port 8080, you can view the sample application at <a href="http://localhost:8080/">http://locahost:8080</a>. For more information on the sample google web application created by the plugin you can refer to <a href="http://code.google.com/appengine/docs/java/gettingstarted/creating.html">Google java app engine documentation</a> .Please keep in mind that intent of this document is not to provide developers the <a href="http://code.google.com/appengine/docs/java/overview.html">overview of Google App engine for Java</a>.</p>
<p><strong>Step4</strong> : By now you are ready with the google app engine infrastructure and we can move to the next step of creating a file upload application in Struts 2.</p>
<ul>
<li>for creating a struts 2 application you will need to first add the required dependencies to the struts2-fileupload project. The required struts 2 jars are below mentioned and you can find these jars in struts2 package you downloaded inside the lib folder :-
<ul>
<li>commons-fileupload-1.2.1.jar</li>
<li>commons-io-1.3.2.jar</li>
<li>commons-logging-1.1.jar</li>
<li>freemarker-2.3.13.jar</li>
<li>ognl-2.6.11.jar</li>
<li>struts2-core-2.1.6.jar</li>
<li>struts2-gae-0.1.jar</li>
<li>xwork-2.1.2.jar</li>
</ul>
</li>
<li>Add these dependencies in your eclipse java build path.</li>
</ul>
<p><img title="s2" src="http://whyjava.wordpress.com/files/2009/10/s2.jpg?w=1024" alt="s2" width="1024" height="518" /></p>
<ul>
<li>Add these dependencies in the war/WEB-INF/lib folder so that these jars gets deployed along with your application.</li>
<li>First step in creating a struts 2 application is configuring the web.xml (deployment descriptor) which is located in WEB-INF folder.You can remove the servlet declaration from web.xml as we will not be needing this.In the <a href="http://whyjava.wordpress.com/2009/08/30/creating-struts2-application-on-google-app-engine-gae/">last post</a>,we configured FilterDispatcher(this is theFilterDispatcher which comes with struts2) but in this application we need to add the GaeFilterDispatcher(this is provided by struts 2 extension framework for GAE). We will declare GaeFilterDispatcher in web.xml, because in struts2 every request goes  pass through a FilterDispatcher, which will invoke the appropriate action corresponding to the URL mapping.So our web.xml will look like :-</li>
</ul>
<pre class="brush: xml;">
&#60;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&#62;
&#60;web-app xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
xmlns=&#34;http://java.sun.com/xml/ns/javaee&#34;
xmlns:web=&#34;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#34;
xsi:schemaLocation=&#34;http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#34; version=&#34;2.5&#34;&#62;
 &#60;filter&#62;
 &#60;filter-name&#62;struts2-gae&#60;/filter-name&#62;
 &#60;filter-class&#62;com.struts2.gae.dispatcher.GaeFilterDispatcher&#60;/filter-class&#62;
 &#60;/filter&#62;
 &#60;filter-mapping&#62;
 &#60;filter-name&#62;struts2-gae&#60;/filter-name&#62;
 &#60;url-pattern&#62;/*&#60;/url-pattern&#62;
 &#60;/filter-mapping&#62;
 &#60;welcome-file-list&#62;
 &#60;welcome-file&#62;index.html&#60;/welcome-file&#62;
 &#60;/welcome-file-list&#62;
&#60;/web-app&#62;
</pre>
<ul>
<li>To start we will be creating a jsp fileupload page using struts 2 tag library and we will call file upload page from index.html.To call the fileupload page there are two ways first, we can directly call the upload.jsp page from link second, we can calling it through struts. We will be taking the second step as this will show you how to configure actions when you dont need to invoke any action.Lets first see how our login page and index.html will look like :-</li>
</ul>
<p><strong>index.html</strong></p>
<pre class="brush: xml;">
&#60;!DOCTYPE HTML PUBLIC &#34;-//W3C//DTD HTML 4.01 Transitional//EN&#34;&#62;
&#60;html&#62;
&#60;head&#62;
&#60;meta http-equiv=&#34;content-type&#34; content=&#34;text/html; charset=UTF-8&#34;&#62;
&#60;title&#62;Struts2 File upload on Google App Engine&#60;/title&#62;
&#60;/head&#62;

&#60;body&#62;
&#60;h1&#62;Struts2 File upload on Google App Engine!&#60;/h1&#62;
&#60;table&#62;
&#60;tr&#62;
&#60;td colspan=&#34;2&#34; style=&#34;font-weight: bold;&#34;&#62;Available Application:&#60;/td&#62;
&#60;/tr&#62;
&#60;tr&#62;
&#60;td&#62;&#60;a href=&#34;/add&#34; /&#62;Upload my Photo&#60;/td&#62;
&#60;/tr&#62;
&#60;/table&#62;
&#60;/body&#62;
&#60;/html&#62;
</pre>
<p><strong>upload.jsp</strong></p>
<pre class="brush: xml;">
&#60;%@ page language=&#34;java&#34; contentType=&#34;text/html; charset=ISO-8859-1&#34;&#60;/pre&#62;
 pageEncoding=&#34;ISO-8859-1&#34;%&#62;
&#60;%@ taglib prefix=&#34;s&#34; uri=&#34;/struts-tags&#34;%&#62;
&#60;!DOCTYPE html PUBLIC &#34;-//W3C//DTD HTML 4.01 Transitional//EN&#34; &#34;http://www.w3.org/TR/html4/loose.dtd&#34;&#62;
&#60;html&#62;
&#60;head&#62;
&#60;meta http-equiv=&#34;Content-Type&#34; content=&#34;text/html; charset=ISO-8859-1&#34;&#62;
&#60;title&#62;Upload my Photo&#60;/title&#62;
&#60;/head&#62;
&#60;body&#62;
 &#60;s:form action=&#34;upload&#34; method=&#34;post&#34; enctype=&#34;multipart/form-data&#34;&#62;
 &#60;s:file name=&#34;photo&#34; label=&#34;Upload new Photo&#34;&#62;&#60;/s:file&#62;
 &#60;s:submit value=&#34;Upload&#34;&#62;&#60;/s:submit&#62;
 &#60;/s:form&#62;

&#60;/body&#62;
&#60;/html&#62;
</pre>
<p>After creating the upload.jsp we need to configure this as action in the struts.xml file which you be should put inside source folder parallel to log4j.properties file.We can configure action as mentioned below:-</p>
<pre class="brush: xml;">
&#60;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&#62;
&#60;!DOCTYPE struts PUBLIC
&#34;-//Apache Software Foundation//DTD Struts Configuration 2.0//EN&#34;
&#34;http://struts.apache.org/dtds/struts-2.0.dtd&#34;&#62;
&#60;struts&#62;
	&#60;include file=&#34;struts-default.xml&#34;&#62;&#60;/include&#62;
&#60;package name=&#34;&#34; namespace=&#34;/&#34; extends=&#34;struts-default&#34;&#62;
		&#60;action name=&#34;add&#34;&#62;
			&#60;result&#62;/upload.jsp&#60;/result&#62;
		&#60;/action&#62;
	&#60;/package&#62;
&#60;/struts&#62;
</pre>
<ul>
<li>Now try running this application by right click on project run as &#62; web application and click <a href="http://localhost:8080">http://localhost:8080</a>. You will see index.html and when you click on upload my photo you will get this exception :-</li>
</ul>
<p><span style="color:#993300;">SEVERE: Unable to set parameter [location] in result of type    [org.apache.struts2.dispatcher.ServletDispatcherResult]</span></p>
<p><span style="color:#993300;">Caught OgnlException while setting property &#8216;location&#8217; on type &#8216;org.apache.struts2.dispatcher.ServletDispatcherResult&#8217;. &#8211; Class: ognl.OgnlRuntime</span></p>
<p><span style="color:#993300;">File: OgnlRuntime.java</span></p>
<p><span style="color:#993300;">Method: invokeMethod</span></p>
<p><span style="color:#993300;">Line: 508 &#8211; ognl/OgnlRuntime.java:508:-1</span></p>
<p><span style="color:#993300;"> at com.opensymphony.xwork2.ognl.OgnlUtil.internalSetProperty(OgnlUtil.java:392)</span></p>
<p><span style="color:#993300;">Caused by: java.lang.IllegalAccessException: Method [public void org.apache.struts2.dispatcher.StrutsResultSupport.setLocation(java.lang.String)] cannot be accessed.</span></p>
<p><span style="color:#993300;"> at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:508)</span></p>
<p><span style="color:#993300;"> at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:812)</span></p>
<p><span style="color:#993300;"> at ognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:964)</span></p>
<p><span style="color:#993300;"> at ognl.ObjectPropertyAccessor.setPossibleProperty(ObjectPropertyAccessor.java:75)</span></p>
<p><span style="color:#993300;"> at ognl.ObjectPropertyAccessor.setProperty(ObjectPropertyAccessor.java:131)</span></p>
<p><span style="color:#993300;"> at com.opensymphony.xwork2.ognl.accessor.ObjectAccessor.setProperty(ObjectAccessor.java:28)</span></p>
<p><span style="color:#993300;"> at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:1656)</span></p>
<p><span style="color:#993300;"> at ognl.ASTProperty.setValueBody(ASTProperty.java:101)</span></p>
<p><span style="color:#993300;"> at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:177)</span></p>
<p><span style="color:#993300;"> at ognl.SimpleNode.setValue(SimpleNode.java:246)</span></p>
<p><span style="color:#993300;"> at ognl.Ognl.setValue(Ognl.java:476)</span></p>
<p><span style="color:#993300;"> at com.opensymphony.xwork2.ognl.OgnlUtil.setValue(OgnlUtil.java:192)</span></p>
<p><span style="color:#993300;"> at com.opensymphony.xwork2.ognl.OgnlUtil.internalSetProperty(OgnlUtil.java:385)</span></p>
<p><span style="color:#993300;"> &#8230; 73 more</span></p>
<ul>
<li>In order to resolve this problem we  need to make entry in web.xml file also for OgnlListener.This OgnlListener is also provided by struts2-gae framework.(A struts2 extension framework for GAE).</li>
</ul>
<pre class="brush: xml;">[/sourcecode]

&#60;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&#62;
&#60;web-app xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
xmlns=&#34;http://java.sun.com/xml/ns/javaee&#34;
xmlns:web=&#34;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#34;
xsi:schemaLocation=&#34;http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#34; version=&#34;2.5&#34;&#62;
&#60;filter&#62;
&#60;filter-name&#62;struts2-gae&#60;/filter-name&#62;
&#60;filter-class&#62;com.struts2.gae.dispatcher.GaeFilterDispatcher&#60;/filter-class&#62;
&#60;/filter&#62;
&#60;filter-mapping&#62;
&#60;filter-name&#62;struts2-gae&#60;/filter-name&#62;
&#60;url-pattern&#62;/*&#60;/url-pattern&#62;
&#60;/filter-mapping&#62;
&#60;listener&#62;
&#60;listener-class&#62;com.struts2.gae.listener.OgnlListener&#60;/listener-class&#62;
&#60;/listener&#62;
&#60;welcome-file-list&#62;
&#60;welcome-file&#62;index.html&#60;/welcome-file&#62;
&#60;/welcome-file-list&#62;
&#60;/web-app&#62;

[sourcecode]</pre>
<ul>
<li>You need to add this step if you are using Google App Engine 1.2.6 because when you run struts2 application on google app engine 1.2.6 you will get the following error:-</li>
</ul>
<p><span style="color:#800000;">javax.servlet.ServletException: java.lang.NoClassDefFoundError: javax.swing.tree.TreeNode is a restricted class. Please see the Google App Engine developer’s guide for more details.<br />
at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:825)<br />
at org.apache.jasper.runtime.PageContextImpl.access$1100(PageContextImpl.java:64)<br />
at org.apache.jasper.runtime.PageContextImpl$12.run(PageContextImpl.java:745)<br />
at java.security.AccessController.doPrivileged(Native Method)<br />
at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:743)<br />
at org.apache.jsp.login_jsp._jspService(login_jsp.java:86)<br />
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)<br />
at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)<br />
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)<br />
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)<br />
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)<br />
at com.google.appengine.tools.development.PrivilegedJspServlet.access$101(PrivilegedJspServlet.java:23)<br />
at com.google.appengine.tools.development.PrivilegedJspServlet$2.run(PrivilegedJspServlet.java:59)<br />
at java.security.AccessController.doPrivileged(Native Method)<br />
at com.google.appengine.tools.development.PrivilegedJspServlet.service(PrivilegedJspServlet.java)</span></p>
<p><span style="color:#800000;"><span style="color:#000000;">To avoid this error you need to create a new package </span></span>&#8220;freemarker.core&#8221;<span style="color:#800000;"><span style="color:#000000;"> in your source folder and add the following class </span></span></p>
<p><span style="color:#800000;"><span style="color:#000000;">
<pre class="brush: java;">&#60;/span&#62;&#60;/span&#62;

/*
 * Copyright (c) 2003 The Visigoth Software Society. All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above
copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowledgement:
 *       &#34;This product includes software developed by the
 *        Visigoth Software Society (http://www.visigoths.org/).&#34;
 *    Alternately, this acknowledgement may appear in the software
itself,
 *    if and wherever such third-party acknowledgements normally
appear.
 *
 * 4. Neither the name &#34;FreeMarker&#34;, &#34;Visigoth&#34;, nor any of the names
of the
 *    project contributors may be used to endorse or promote products
derived
 *    from this software without prior written permission. For written
 *    permission, please contact visigo...@visigoths.org.
 *
 * 5. Products derived from this software may not be called
&#34;FreeMarker&#34; or &#34;Visigoth&#34;
 *    nor may &#34;FreeMarker&#34; or &#34;Visigoth&#34; appear in their names
 *    without prior written permission of the Visigoth Software
Society.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Visigoth Software Society. For more
 * information on the Visigoth Software Society, please see
 * http://www.visigoths.org/
 */

package freemarker.core;

import java.io.IOException;

/**
 * A TemplateElement representing a block of plain text.
 *
 * @version $Id: TextBlock.java,v 1.17 2004/01/06 17:06:42 szegedia Exp $
 */
public final class TextBlock extends TemplateElement {
 private static final char[] EMPTY_CHAR_ARRAY = new char[0];
 static final TextBlock EMPTY_BLOCK = new TextBlock(EMPTY_CHAR_ARRAY, false);
 // We're using char[] instead of String for storing the text block because
 // Writer.write(String) involves copying the String contents to a char[]
 // using String.getChars(), and then calling Writer.write(char[]).By
 // using Writer.write(char[]) directly, we avoid array copying on each
 // write.
 private char[] text;
 private final boolean unparsed;

 public TextBlock(String text) {
 this(text, false);
 }

 public TextBlock(String text, boolean unparsed) {
 this(text.toCharArray(), unparsed);
 }

 private TextBlock(char[] text, boolean unparsed) {
 this.text = text;
 this.unparsed = unparsed;
 }

 /**
 * Simply outputs the text.
 */
 public void accept(Environment env) throws IOException {
 env.getOut().write(text);
 }

 public String getCanonicalForm() {
 String text = new String(this.text);
 if (unparsed) {
 return &#34;&#60;#noparse&#62;&#34; + text + &#34;&#60;/#noparse&#62;&#34;;
 }
 return text;
 }

 public String getDescription() {
 String s = new String(text).trim();
 if (s.length() == 0) {
 return &#34;whitespace&#34;;
 }
 if (s.length() &#62; 20) {
 s = s.substring(0, 20) + &#34;...&#34;;
 s = s.replace('\n', ' ');
 s = s.replace('\r', ' ');
 }
 return &#34;text block (&#34; + s + &#34;)&#34;;
 }

 TemplateElement postParseCleanup(boolean stripWhitespace) {
 if (text.length == 0)
 return this;
 int openingCharsToStrip = 0, trailingCharsToStrip = 0;
 boolean deliberateLeftTrim = deliberateLeftTrim();
 boolean deliberateRightTrim = deliberateRightTrim();
 if (!stripWhitespace &#124;&#124; text.length == 0) {
 return this;
 }
 if (parent.parent == null &#38;&#38; previousSibling() == null)
 return this;
 if (!deliberateLeftTrim) {
 trailingCharsToStrip = trailingCharsToStrip();
 }
 if (!deliberateRightTrim) {
 openingCharsToStrip = openingCharsToStrip();
 }
 if (openingCharsToStrip == 0 &#38;&#38; trailingCharsToStrip == 0) {
 return this;
 }
 this.text = substring(text, openingCharsToStrip, text.length
 - trailingCharsToStrip);
 if (openingCharsToStrip &#62; 0) {
 this.beginLine++;
 this.beginColumn = 1;
 }
 if (trailingCharsToStrip &#62; 0) {
 this.endColumn = 0;
 }
 return this;
 }

 /**
 * Scans forward the nodes on the same line to see whether there is a
 * deliberate left trim in effect. Returns true if the left trim was
 * present.
 */
 private boolean deliberateLeftTrim() {
 boolean result = false;
 for (TemplateElement elem = this.nextTerminalNode(); elem != null
 &#38;&#38; elem.beginLine == this.endLine; elem = elem
 .nextTerminalNode()) {
 if (elem instanceof TrimInstruction) {
 TrimInstruction ti = (TrimInstruction) elem;
 if (!ti.left &#38;&#38; !ti.right) {
 result = true;
 }
 if (ti.left) {
 result = true;
 int lastNewLineIndex = lastNewLineIndex();
 if (lastNewLineIndex &#62;= 0 &#124;&#124; beginColumn == 1) {
 char[] firstPart = substring(text, 0,
 lastNewLineIndex + 1);
 char[] lastLine = substring(text, 1 + lastNewLineIndex);
 if (trim(lastLine).length == 0) {
 this.text = firstPart;
 this.endColumn = 0;
 } else {
 int i = 0;
 while (Character.isWhitespace(lastLine[i])) {
 i++;
 }
 char[] printablePart = substring(lastLine, i);
 this.text = concat(firstPart, printablePart);
 }
 }
 }
 }
 }
 if (result) {
 }
 return result;
 }

 /**
 * Checks for the presence of a t or rt directive on the same line. Returns
 * true if the right trim directive was present.
 */
 private boolean deliberateRightTrim() {
 boolean result = false;
 for (TemplateElement elem = this.prevTerminalNode(); elem != null
 &#38;&#38; elem.endLine == this.beginLine; elem = elem
 .prevTerminalNode()) {
 if (elem instanceof TrimInstruction) {
 TrimInstruction ti = (TrimInstruction) elem;
 if (!ti.left &#38;&#38; !ti.right) {
 result = true;
 }
 if (ti.right) {
 result = true;
 int firstLineIndex = firstNewLineIndex() + 1;
 if (firstLineIndex == 0) {
 return false;
 }
 if (text.length &#62; firstLineIndex
 &#38;&#38; text[firstLineIndex - 1] == '\r'
 &#38;&#38; text[firstLineIndex] == '\n') {
 firstLineIndex++;
 }
 char[] trailingPart = substring(text, firstLineIndex);
 char[] openingPart = substring(text, 0, firstLineIndex);
 if (trim(openingPart).length == 0) {
 this.text = trailingPart;
 this.beginLine++;
 this.beginColumn = 1;
 } else {
 int lastNonWS = openingPart.length - 1;
 while (Character.isWhitespace(text[lastNonWS])) {
 lastNonWS--;
 }
 char[] printablePart = substring(text, 0, lastNonWS + 1);
 if (trim(trailingPart).length == 0) {
 // THIS BLOCK IS HEINOUS! THERE MUST BE A BETTER
 // WAY! REVISIT (JR)
 boolean trimTrailingPart = true;
 for (TemplateElement te = this.nextTerminalNode(); te != null
 &#38;&#38; te.beginLine == this.endLine; te = te
 .nextTerminalNode()) {
 if (te.heedsOpeningWhitespace()) {
 trimTrailingPart = false;
 }
 if (te instanceof TrimInstruction
 &#38;&#38; ((TrimInstruction) te).left) {
 trimTrailingPart = true;
 break;
 }
 }
 if (trimTrailingPart)
 trailingPart = EMPTY_CHAR_ARRAY;
 }
 this.text = concat(printablePart, trailingPart);
 }
 }
 }
 }
 return result;
 }

 /*
 * private String leftTrim(String s) { int i =0; while (i&#60;s.length()) { if
 * (!Character.isWhitespace(s.charAt(i))) break; ++i; } return
 * s.substring(i); }
 */
 private int firstNewLineIndex() {
 String content = new String(text);
 int newlineIndex1 = content.indexOf('\n');
 int newlineIndex2 = content.indexOf('\r');
 int result = newlineIndex1 &#62;= 0 ? newlineIndex1 : newlineIndex2;
 if (newlineIndex1 &#62;= 0 &#38;&#38; newlineIndex2 &#62;= 0) {
 result = Math.min(newlineIndex1, newlineIndex2);
 }
 return result;
 }

 private int lastNewLineIndex() {
 String content = new String(text);
 return Math.max(content.lastIndexOf('\r'), content.lastIndexOf('\n'));
 }

 /**
 * figures out how many opening whitespace characters to strip in the
 * post-parse cleanup phase.
 */
 private int openingCharsToStrip() {
 int newlineIndex = firstNewLineIndex();
 if (newlineIndex == -1 &#38;&#38; beginColumn != 1) {
 return 0;
 }
 ++newlineIndex;
 if (text.length &#62; newlineIndex) {
 if (newlineIndex &#62; 0 &#38;&#38; text[newlineIndex - 1] == '\r'
 &#38;&#38; text[newlineIndex] == '\n') {
 ++newlineIndex;
 }
 }
 if (new String(text).substring(0, newlineIndex).trim().length() &#62; 0) {
 return 0;
 }
 // We look at the preceding elements on the line to see if we should
 // strip the opening newline and any whitespace preceding it.
 for (TemplateElement elem = this.prevTerminalNode(); elem != null
 &#38;&#38; elem.endLine == this.beginLine; elem = elem
 .prevTerminalNode()) {
 if (elem.heedsOpeningWhitespace()) {
 return 0;
 }
 }
 return newlineIndex;
 }

 /**
 * figures out how many trailing whitespace characters to strip in the
 * post-parse cleanup phase.
 */
 private int trailingCharsToStrip() {
 String content = new String(text);
 int lastNewlineIndex = lastNewLineIndex();
 if (lastNewlineIndex == -1 &#38;&#38; beginColumn != 1) {
 return 0;
 }
 String substring = content.substring(lastNewlineIndex + 1);
 if (substring.trim().length() &#62; 0) {
 return 0;
 }
 // We look at the elements afterward on the same line to see if we
 // should strip any whitespace after the last newline
 for (TemplateElement elem = this.nextTerminalNode(); elem != null
 &#38;&#38; elem.beginLine == this.endLine; elem = elem
 .nextTerminalNode()) {
 if (elem.heedsTrailingWhitespace()) {
 return 0;
 }
 }
 return substring.length();
 }

 boolean heedsTrailingWhitespace() {
 if (isIgnorable()) {
 return false;
 }
 for (int i = 0; i &#60; text.length; i++) {
 char c = text[i];
 if (c == '\n' &#124;&#124; c == '\r') {
 return false;
 }
 if (!Character.isWhitespace(c)) {
 return true;
 }
 }
 return true;
 }

 boolean heedsOpeningWhitespace() {
 if (isIgnorable()) {
 return false;
 }
 for (int i = text.length - 1; i &#62;= 0; i--) {
 char c = text[i];
 if (c == '\n' &#124;&#124; c == '\r') {
 return false;
 }
 if (!Character.isWhitespace(c)) {
 return true;
 }
 }
 return true;
 }

 boolean isIgnorable() {
 if (text == null &#124;&#124; text.length == 0) {
 return true;
 }
 if (!isWhitespace()) {
 return false;
 }
 // trick here
 boolean atTopLevel = true;
 TemplateElement prevSibling = previousSibling();
 TemplateElement nextSibling = nextSibling();
 return ((prevSibling == null &#38;&#38; atTopLevel) &#124;&#124; nonOutputtingType(prevSibling))
 &#38;&#38; ((nextSibling == null &#38;&#38; atTopLevel) &#124;&#124; nonOutputtingType(nextSibling));
 }

 private boolean nonOutputtingType(TemplateElement element) {
 return (element instanceof Macro &#124;&#124; element instanceof Assignment
 &#124;&#124; element instanceof AssignmentInstruction
 &#124;&#124; element instanceof PropertySetting
 &#124;&#124; element instanceof LibraryLoad &#124;&#124; element instanceof Comment);
 }

 private static char[] substring(char[] c, int from, int to) {
 char[] c2 = new char[to - from];
 System.arraycopy(c, from, c2, 0, c2.length);
 return c2;
 }

 private static char[] substring(char[] c, int from) {
 return substring(c, from, c.length);
 }

 private static char[] trim(char[] c) {
 if (c.length == 0) {
 return c;
 }
 return new String(c).trim().toCharArray();
 }

 private static char[] concat(char[] c1, char[] c2) {
 char[] c = new char[c1.length + c2.length];
 System.arraycopy(c1, 0, c, 0, c1.length);
 System.arraycopy(c2, 0, c, c1.length, c2.length);
 return c;
 }

 boolean isWhitespace() {
 return text == null &#124;&#124; trim(text).length == 0;
 }

}
</pre>
<p></span></span></p>
<ul>
<li>Now if you run the web application you will see the upload page.</li>
<li>Next step is to configure the GaeFileUploadInterceptor in struts.xml file.In struts 2, file upload is done by FileUploadInterceptor which intercept all the MultiPartRequest and provides the File object to the action. Then action does what ever it wants to do with the File object.But, on google app engine you can&#8217;t get the File object because file writes and many other file related operations are not allowed on GAE.So, we will use GaeFileUploadInterceptor which provides a String object which contains all the file content.You can save this string as a blob into the datastore or convert this string object into InputStream and return to the user.You need to add an entry in struts.xml for GaeFileUploadInterceptor.</li>
</ul>
<pre class="brush: xml;">&#60;/pre&#62;
&#60;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&#62;
&#60;!DOCTYPE struts PUBLIC
&#34;-//Apache Software Foundation//DTD Struts Configuration 2.0//EN&#34;
&#34;http://struts.apache.org/dtds/struts-2.0.dtd&#34;&#62;
&#60;struts&#62;
&#60;include file=&#34;struts-default.xml&#34;&#62;&#60;/include&#62;
&#60;package name=&#34;&#34; namespace=&#34;/&#34; extends=&#34;struts-default&#34;&#62;
&#60;interceptors&#62;
&#60;interceptor name=&#34;gaeFileUploadInterceptor&#34;
class=&#34;com.struts2.gae.interceptor.GaeFileUploadInterceptor&#34; /&#62;
&#60;interceptor-stack name=&#34;fileUploadStack&#34;&#62;
&#60;interceptor-ref name=&#34;gaeFileUploadInterceptor&#34;&#62;&#60;/interceptor-ref&#62;
&#60;interceptor-ref name=&#34;basicStack&#34;&#62;&#60;/interceptor-ref&#62;
&#60;/interceptor-stack&#62;
&#60;/interceptors&#62;

&#60;default-interceptor-ref name=&#34;fileUploadStack&#34; /&#62;
&#60;action name=&#34;add&#34;&#62;
&#60;result&#62;/upload.jsp&#60;/result&#62;
&#60;/action&#62;
&#60;/package&#62;

&#60;/struts&#62;
&#60;pre&#62;</pre>
<ul>
<li>Next step is to create the UploadAction which will handle the upload request.</li>
</ul>
<pre class="brush: java;">

package com.fileupload;

import java.io.InputStream;

import org.apache.commons.io.IOUtils;

import com.opensymphony.xwork2.ActionSupport;

public class UploadAction extends ActionSupport {

 private static final long serialVersionUID = -300329750248730163L;
 private String photo;
 private String photoContentType;
 private String photoFileName;
 private InputStream photoStream;

 public String upload() throws  Exception {
 photoStream = IOUtils.toInputStream(photo,&#34;ISO-8859-1&#34;);
 return &#34;success&#34;;
 }

 public String getPhoto() {
 return photo;
 }

 public void setPhoto(String photo) {
 this.photo = photo;
 }

 public String getPhotoContentType() {
 return photoContentType;
 }

 public void setPhotoContentType(String photoContentType) {
 this.photoContentType = photoContentType;
 }

 public String getPhotoFileName() {
 return photoFileName;
 }

 public void setPhotoFileName(String photoFileName) {
 this.photoFileName = photoFileName;
 }

 public InputStream getPhotoStream() {
 return photoStream;
 }

 public void setPhotoStream(InputStream photoStream) {
 this.photoStream = photoStream;
 }
}
</pre>
<p>If you notice there are three properties in the action photo,photoContentType,photoFileName.These properties get their values from the GaeFileUploadInterceptor. These properties have to start with name you gave the file in the upload.jsp <strong>&#60;s:file name=&#8221;photo&#8221; label=&#8221;Upload new Photo&#8221;&#62;&#60;/s:file&#62;</strong>. In this, name is &#8220;photo&#8221; so you will get your file content in a property called photo and the two other properties will start with photo.</p>
<p>The second thing to notice is that result of action is &#8220;success&#8221; which is not SUCCESS you normally use. In this we are using a different result type called org.apache.struts2.dispatcher.StreamResult. Stream result is a custom Result type for sending raw data (via an InputStream) directly to the HttpServletResponse.</p>
<ul>
<li>Now we will configure UploadAction in struts.xml</li>
</ul>
<pre class="brush: xml;">

&#60;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&#62;
&#60;!DOCTYPE struts PUBLIC
&#34;-//Apache Software Foundation//DTD Struts Configuration 2.0//EN&#34;
&#34;http://struts.apache.org/dtds/struts-2.0.dtd&#34;&#62;
&#60;struts&#62;
 &#60;include file=&#34;struts-default.xml&#34;&#62;&#60;/include&#62;
 &#60;package name=&#34;&#34; namespace=&#34;/&#34; extends=&#34;struts-default&#34;&#62;
 &#60;interceptors&#62;
 &#60;interceptor name=&#34;gaeFileUploadInterceptor&#34;
 class=&#34;com.struts2.gae.interceptor.GaeFileUploadInterceptor&#34; /&#62;
 &#60;interceptor-stack name=&#34;fileUploadStack&#34;&#62;
 &#60;interceptor-ref name=&#34;gaeFileUploadInterceptor&#34;&#62;&#60;/interceptor-ref&#62;
 &#60;interceptor-ref name=&#34;basicStack&#34;&#62;&#60;/interceptor-ref&#62;
 &#60;/interceptor-stack&#62;
 &#60;/interceptors&#62;

 &#60;default-interceptor-ref name=&#34;fileUploadStack&#34; /&#62;
 &#60;action name=&#34;add&#34;&#62;
 &#60;result&#62;/upload.jsp&#60;/result&#62;
 &#60;/action&#62;
 &#60;action name=&#34;upload&#34; method=&#34;upload&#34;&#62;
 &#60;result name=&#34;success&#34; type = &#34;stream&#34;&#62;
 &#60;param name=&#34;contentType&#34;&#62;image/jpeg&#60;/param&#62;
 &#60;param name=&#34;inputName&#34;&#62;photoStream&#60;/param&#62;
 &#60;param name=&#34;contentDisposition&#34;&#62;filename=&#34;photo.jpg&#34;&#60;/param&#62;
 &#60;param name=&#34;bufferSize&#34;&#62;1024&#60;/param&#62;
 &#60;/result&#62;
 &#60;/action&#62;
 &#60;/package&#62;

&#60;/struts&#62;
</pre>
<ul>
<li>Finally, Run this application you will be able to upload the photo and then view it in your browser.</li>
</ul>
<p>In this blog, i have tried to explain you how you can do file upload using struts 2 on google app engine.Please make sure you download the <a href="http://code.google.com/p/struts2-gae/">struts2-gae jar</a>.Hope this helps you all.</p>
<p>You can dowload the sample project from <a href="http://code.google.com/p/struts2-gae/downloads/list">here</a>.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[ASP.NET FileUpload and File.Open() method problems]]></title>
<link>http://praveenbattula.wordpress.com/2009/09/25/asp-net-fileupload-and-file-open-method-problems/</link>
<pubDate>Fri, 25 Sep 2009 06:30:10 +0000</pubDate>
<dc:creator>praveen battula</dc:creator>
<guid>http://praveenbattula.wordpress.com/2009/09/25/asp-net-fileupload-and-file-open-method-problems/</guid>
<description><![CDATA[ASP.NET FileUpload and File.Open() method problems]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a href="http://praveenbattula.blogspot.com/2009/06/aspnet-fileupload-on-sharepoint-custom.html">ASP.NET FileUpload and File.Open() method problems</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[File upload using Struts Framework]]></title>
<link>http://faahsaii.wordpress.com/2009/09/15/file-upload-using-struts-framework/</link>
<pubDate>Tue, 15 Sep 2009 08:02:00 +0000</pubDate>
<dc:creator>faahsaii</dc:creator>
<guid>http://faahsaii.wordpress.com/2009/09/15/file-upload-using-struts-framework/</guid>
<description><![CDATA[เนื่องจากท่านเบนซ์เรียกร้องมาว่าอยากให้เดโม struts upload ให้ดูหน่อย นั่งไตร่ตรองอยู่พักนึง และก็อืม]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><span style="font-size:85%;"><span style="font-family:verdana;">เนื่องจากท่านเบนซ์เรียกร้องมาว่าอยากให้เดโม struts upload ให้ดูหน่อย นั่งไตร่ตรองอยู่พักนึง และก็อืมๆๆ ได้ๆ ทำก็ทำ ฮ่าฮ่า รับปากมาหลายวันและ กว่าจะได้ฤกษ์ทำก็วันนี้แหละ ตอนตีสองครึ่งด้วย ฮ่าฮ่า ได้ข่าวว่าพุ่งนี้เรียนเช้านี่นา แหะๆ มาๆ เริ่มกันดีกว่า หุหุ ตอนแรกก็นานมากกว่าจะนั่งระลึกชาติได้ว่าทำอะไรก่อนอะไรหลัง อันนั้นอันนี้คืออะไร เพราะเรียนมาแล้วไม่ได้ทวน Error500 กันไปหลายรอบ กว่าจะได้ ทำให้เห็นความสำคัญของ struts-config มากขึ้นอีกสามเท่า 55+ (พี่เม้งชวนคุย แว๊ก ตีสามแล้ว)</span></span><br /><span style="font-size:85%;"><span style="font-family:verdana;"><br />เริ่มจิงๆ เถอะ ฮ่าฮ่า</span></span><br /><span style="font-size:85%;"><span style="font-family:verdana;"><br />ขอเดโมเฉยๆ ละกันนะ ไม่อยากพูดถึงทฤษฎีมาก เพราะง่วง บวกกับ ยังไม่แม่นเท่าไหร่</p>
<p>เริ่มแรก ก็สร้าง Project ขึ้นมาก่อน อย่าลืม เลือกใช้ struts framework ด้วยล่ะ อิอิ ในที่นี้สร้าง project ชื่อ StrutsUpload<br /></span></span>
<div style="text-align:center;"><a href="http://faahsaii.wordpress.com/files/2009/09/choosefw.gif"><img src="http://faahsaii.wordpress.com/files/2009/09/choosefw.gif?w=300" alt="" border="0" /></a></div>
<p><span style="font-size:85%;"><span style="font-family:verdana;">จำไม่ได้เหมือนกันว่าจิงๆ มันต้องสร้างอะไรขึ้นมาก่อน ระหว่าง jso กับ strutsActionForm หรือว่าอะไรก็ได้ เอาเป็นว่าขอสร้าง ActionForm ก่อนละกัน ในที่นี้สร้าง strutsActionForm ชื่อ FileActionForm</p>
<p>พอได้ FileActionForm มาแล้วก็ลบ Attribute เดิม กับ setter, getter method ทิ้งไป แล้วก็สร้าง attribute กับ setter, getter อันใหม่ขึ้นมา อันนี้เราจะเอาไว้เก็บ file ที่จะอัพโหลดขึ้นมา</p>
<blockquote><p>private FormFile file;</p>
<p>public FormFile getFile() {<br />  return file;<br />}</p>
<p>public void setFile(FormFile file) {<br />  this.file = file;<br />}</p></blockquote>
<p>หลังจากนั้นก็ไปแก้ใน method validate ให้มันเช็กว่ามีการรับไฟล์เข้ามาจิงไหม (ซึ่งจิงๆ เอาไปรันแล้ว มันก็ไม่ยอมเช็คให้ &#8211; -&#8221; ไม่เข้าใจมันเหมือนกัน 555+)<br />
<blockquote>    public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {<br />  ActionErrors errors = new ActionErrors();<br />  if (getFile() == null) {<br />      errors.add(&#8220;file&#8221;, new ActionMessage(&#8220;error.name.file&#8221;));<br />  }<br />  return errors;<br />}</p></blockquote>
<p>เพื่อกันลืม ก็ไปใส่ข้อความที่จะให้ขึ้นตอน error ที่ ApplicationResource.properties ใน package com.myapp.struts ก็เพิ่มบรรทัดสุดท้ายเป็น<br />
<blockquote>error.name.file=You must select file first<br />สังเกตว่า ชื่อ error จะต้องตรงกับ ชื่อ argument ใน ActionMessage ของข้างบนนะ</p></blockquote>
<p>เสร็จละโปรเจค เอ้ย!! ไม่ใช่ๆ ต่อไปก็มาทำ jsp (ต้องทำก่อนที่จะทำ action นะ ไม่งั้นมันไม่รู้ว่าจะ action ไปที่ไหน)</p>
<p>สร้าง JSP ขึ้นมา ในที่นี้ตั้งชื่อว่า upload.jsp อย่าลืม add taglib ของ struts เข้าไปด้วยนะ<br />
<blockquote></blockquote>
<p>แล้วก็สร้างฟอร์มสำหรับเลือกไฟล์ที่จะ upload ให้ action ไปที่ uploadFile (ต่อไปก็จะต้องกำหนดเป็น URL-path ของ action)</span></span><span style="font-size:85%;"><span style="font-family:verdana;"><br />
<blockquote><a href="http://faahsaii.wordpress.com/files/2009/09/jsp1.gif"><img src="http://faahsaii.wordpress.com/files/2009/09/jsp1.gif?w=300" alt="" border="0" /></a></p></blockquote>
<p>ก็เป็นอันเสร็จ JSP ต่อไปก็ต้องสร้าง Action ขึ้นมา เพื่อใช้ในการ copy file ที่ได้รับมาจาก jsp เริ่มรู้สึกแล้วสินะว่าทำไมมันต้องสร้างอารายเยอะแยะ ฮ่าฮ่า ก็รู้สึกเหมือนกันนะ แต่เค้าว่ามาอย่างงี้ ก็ต้องจำๆ กันหน่อย ฮึบบบ ^^</p>
<p>สร้าง Action ที่ชื่อ uploadAction อยู่ใน package actions อันนี้เราให้ action กับ upload.jsp</p>
<p></span></span>
<div style="text-align:center;"><span><span><span style="font-size:85%;"><span style="font-family:verdana;"><span><span><span style="font-size:85%;"><span style="font-family:verdana;"><span><span><span style="font-size:85%;"><span style="font-family:verdana;"><a href="http://faahsaii.wordpress.com/files/2009/09/creataction.gif"><img src="http://faahsaii.wordpress.com/files/2009/09/creataction.gif?w=300" alt="" border="0" /></a></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p><a href="http://faahsaii.wordpress.com/files/2009/09/creataction2.gif"><img src="http://faahsaii.wordpress.com/files/2009/09/creataction2.gif?w=300" alt="" border="0" /></a></div>
<p><span style="font-size:85%;"><span style="font-family:verdana;"><br />พอสร้างเสร็จลองไปแอบดูใน struts-config จะพบว่ามี mapping เพิ่มขึ้นมา<br />
<blockquote>      <a href="http://faahsaii.wordpress.com/files/2009/09/xml.gif"><img src="http://faahsaii.wordpress.com/files/2009/09/xml.gif?w=300" alt="" border="0" /></a></p></blockquote>
<p>ต่อไปก็ไปเพิ่มโค้ดใน method ActionForward คือในนี้เราต้องเขียนให้มันรับไฟล์มาจากฟอร์ม แล้วก็เขียนลงไปบนคอมเรา ตำแหน่งไหนก็ว่ากันไป จากการที่ลองแล้ว ถ้าใช้ FileWriter เขียน จะเขียนไฟล์ภาพไรงี้ไม่ได้ แต่ถ้าใช้ FileOutputStream ก็เขียนได้หมด</p>
<p>อันดับแรกก็ให้แปลง ActionForm ที่เป็น parameter ของ method ให้เป็น object ของ FileActionForm ที่เราสร้างเอาไว้ก่อน หลังจากนั้นก็ getFile เข้ามาใส่ใน FormFile แล้วก็ getFilename มาเพื่อที่จะให้เป็นชื่อของไฟล์ที่เราจะบันทึกลงไป<br />
<blockquote>        FileActionForm f = (FileActionForm) form;<br />    FormFile file = f.getFile();<br />    String filename = file.getFileName();</p></blockquote>
<p>หลังจากนั้นก็เปิด FileOutputStream แล้วก็เขียนลงไป แล้วก็ปิด แค่นี้ ก็เสร็จ ฮ่าฮ่า<br />
<blockquote>        FileOutputStream fout = new FileOutputStream(&#8220;c:/&#8221; + filename);<br />    fout.write(file.getFileData());<br />    fout.close();</p></blockquote>
<p>แต่จิงๆ ก็ยังไม่เสร็จนะ ฮ่าฮ่า อีกนิดๆ สังเกตว่าใน method มันจะ return mapping.findForward(SUCCESS);<br />ซึ่งเราต้องไปสร้างไฟล์ที่จะให้มัน map กับ success ขึ้นมาก่อน ก็สมมติสร้าง success.html ละกัน ข้างในก็พิมข้อความง่ายๆ<br />แล้วก็ไปเพิ่มตรง  ใน struts-config ให้มันรู้จัก success ของเราก่อน<br /></span><br />
<blockquote><a href="http://faahsaii.wordpress.com/files/2009/09/mxlfwd.gif"><img src="http://faahsaii.wordpress.com/files/2009/09/mxlfwd.gif?w=300" alt="" border="0" /></a><br /><span style="font-family:verdana;">     </span></p></blockquote>
<p><span style="font-family:verdana;">ก็ลองรันดู แล้วก็ลองเลือกไฟล์ไปดู ก็จะพบว่ามันสร้างไฟล์ให้จิงๆ ว๊าวววววววตื่นเต้น</p>
<p>กว่าจะเสร็จ T^T จาตีสี่แล้วววว ตายห่าาา พุ่งนี้เรียนเว็บโปร แงๆๆๆ</p>
<p>ไปนอนละคับพี่น้อง TT<br />
<blockquote></blockquote>
<p></span></span></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Upload an Image by a PHP File]]></title>
<link>http://kaktaruas.wordpress.com/2009/09/13/upload-an-image-by-a-php-file/</link>
<pubDate>Sun, 13 Sep 2009 06:04:58 +0000</pubDate>
<dc:creator>kaktaruas</dc:creator>
<guid>http://kaktaruas.wordpress.com/2009/09/13/upload-an-image-by-a-php-file/</guid>
<description><![CDATA[Firstly we need a form that can upload an image to save with PHP. This could be something like this:]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Firstly we need a form that can upload an image to save with PHP. This could be something like this:</p>
<pre style="border:1px solid #d9d9d9;background:#f1f4f7 none repeat scroll 0 0;overflow:auto;color:#000066;font-family:Arial,Courier,monospace;font-style:normal;font-variant:normal;font-weight:normal;font-size:1.3em;line-height:normal;padding:5px;">&#60;form action="./upload.php" method="post" enctype="multipart/form-data"&#62;
   &#60;p&#62;
      &#60;label for="file"&#62;Select a file:&#60;/label&#62; &#60;input type="file" name="userfile" id="file"&#62; &#60;br /&#62;
      &#60;button&#62;Upload File&#60;/button&#62;
   &#60;p&#62;
&#60;/form&#62;</pre>
<p>On line one we tell the form to send the information to our PHP file (which we will create later) named upload.php, we then tell the form to send the information as &#8220;multipart/form-data&#8221;, this is required to send files through the form. Then we create an input with type=&#8221;file&#8221;, this makes an input with the required buttons to select a file. Finally we add a button to submit the form.</p>
<div>
<p>Now we can create our upload.php file. To start we&#8217;ll check that the file upload is safe by setting a list of allowed filetypes and disallowing all other file uploads. This will prevent people from uploading malicious files. Then we will check the filesize to prevent large files from being uploaded.</p>
<pre style="border:1px solid #d9d9d9;background:#f1f4f7 none repeat scroll 0 0;overflow:auto;color:#000066;font-family:Arial,Courier,monospace;font-style:normal;font-variant:normal;font-weight:normal;font-size:1.3em;line-height:normal;padding:5px;">&#60;?php
   // Configuration - Your Options
      $allowed_filetypes = array('.jpg','.gif','.bmp','.png'); // These will be the types of file that will pass the validation.
      $max_filesize = 524288; // Maximum filesize in BYTES (currently 0.5MB).
      $upload_path = './files/'; // The place the files will be uploaded to (currently a 'files' directory).

   $filename = $_FILES['userfile']['name']; // Get the name of the file (including file extension).
   $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Get the extension from the filename.

   // Check if the filetype is allowed, if not DIE and inform the user.
   if(!in_array($ext,$allowed_filetypes))
      die('The file you attempted to upload is not allowed.');

   // Now check the filesize, if it is too large then DIE and inform the user.
   if(filesize($_FILES['userfile']['tmp_name']) &#62; $max_filesize)
      die('The file you attempted to upload is too large.');

   // Check if we can upload to the specified path, if not DIE and inform the user.
   if(!is_writable($upload_path))
      die('You cannot upload to the specified directory, please CHMOD it to 777.');

   // We'll start handling the upload in the next step

?&#62;</pre>
<p>It&#8217;s worth noting, that by default PHP will not handle file uploads larger than 2MB, if you require PHP to handle larger files then you must first set upload_max_filesize and post_max_size in your php.ini file to be larger than 2MB.</p>
<p><!-- div.tutorial-instructions --></div>
<p><!-- div.tutorial-step --></p>
<div>
<h4>Step 3</h4>
<div>
<p>Now that we know we have a suitably small file of a safe filetype we can upload it to where we want it to go. Using the same file:</p>
<pre style="border:1px solid #d9d9d9;background:#f1f4f7 none repeat scroll 0 0;overflow:auto;color:#000066;font-family:Arial,Courier,monospace;font-style:normal;font-variant:normal;font-weight:normal;font-size:1.3em;line-height:normal;padding:5px;">&#60;?php
   // Configuration - Your Options
      $allowed_filetypes = array('.jpg','.gif','.bmp','.png'); // These will be the types of file that will pass the validation.
      $max_filesize = 524288; // Maximum filesize in BYTES (currently 0.5MB).
      $upload_path = './files/'; // The place the files will be uploaded to (currently a 'files' directory).

   $filename = $_FILES['userfile']['name']; // Get the name of the file (including file extension).
   $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Get the extension from the filename.

   // Check if the filetype is allowed, if not DIE and inform the user.
   if(!in_array($ext,$allowed_filetypes))
      die('The file you attempted to upload is not allowed.');

   // Now check the filesize, if it is too large then DIE and inform the user.
   if(filesize($_FILES['userfile']['tmp_name']) &#62; $max_filesize)
      die('The file you attempted to upload is too large.');

   // Check if we can upload to the specified path, if not DIE and inform the user.
   if(!is_writable($upload_path))
      die('You cannot upload to the specified directory, please CHMOD it to 777.');

   // Upload the file to your specified path.
   if(move_uploaded_file($_FILES['userfile']['tmp_name'],$upload_path . $filename))
         echo 'Your file upload was successful, view the file &#60;a href="' . $upload_path . $filename . '" title="Your File"&#62;here&#60;/a&#62;'; // It worked.
      else
         echo 'There was an error during the file upload.  Please try again.'; // It failed <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> .

?&#62;</pre>
<p>There you have it! A safe and suitable upload script.</p>
<p><!-- div.tutorial-instructions --></div>
<p><!-- div.tutorial-step --></div>
<h4>Step 4</h4>
<p>For more information look through the Handling File Uploads section at <a href="http://php.net/manual/en/features.file-upload.php"> php.net</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Paperclip with Rails for image manipulation]]></title>
<link>http://purab.wordpress.com/2009/09/10/paperclip-with-rails-for-image-manipulation/</link>
<pubDate>Thu, 10 Sep 2009 11:11:42 +0000</pubDate>
<dc:creator>Purab</dc:creator>
<guid>http://purab.wordpress.com/2009/09/10/paperclip-with-rails-for-image-manipulation/</guid>
<description><![CDATA[I used the spree e-Commerce CMS for checking or R&amp;D of Spree code. Spree is the really nice and ]]></description>
<content:encoded><![CDATA[I used the spree e-Commerce CMS for checking or R&amp;D of Spree code. Spree is the really nice and ]]></content:encoded>
</item>
<item>
<title><![CDATA[How to build a simple php file upload]]></title>
<link>http://jony.wordpress.com/2009/09/08/how-to-build-a-simple-php-file-upload/</link>
<pubDate>Tue, 08 Sep 2009 19:58:16 +0000</pubDate>
<dc:creator>jony</dc:creator>
<guid>http://jony.wordpress.com/2009/09/08/how-to-build-a-simple-php-file-upload/</guid>
<description><![CDATA[]]></description>
<content:encoded><![CDATA[<div class='snap_preview'></div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Google's utils - sau - cum poti stoca fisiere mari in contul de Gmail]]></title>
<link>http://itbulk.wordpress.com/2009/08/21/googles-utils-sau-cum-poti-stoca-fisiere-mari-in-contul-de-gmail/</link>
<pubDate>Fri, 21 Aug 2009 21:00:34 +0000</pubDate>
<dc:creator>m4niac</dc:creator>
<guid>http://itbulk.wordpress.com/2009/08/21/googles-utils-sau-cum-poti-stoca-fisiere-mari-in-contul-de-gmail/</guid>
<description><![CDATA[Nu cred ca este cineva care sa nu-si smulga parul din cap pentru ca nu a facut backup, pana chiar si]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Nu cred ca este cineva care sa nu-si smulga parul din cap pentru ca nu a facut backup, pana chiar si la o mica chestie. Ca multi altii si eu am pierdut multe, dintr-o simpla formatare facuta in graba sau intr-un exces de entuziasm cauzat de vreun nou sistem de operare furnizat de microshit. Dupa ce in urma cu cateva luni am pierdut cam 2 ani de munca (recuperati din fericire in cele din urma&#8230; dar nu in totalitate, ci cam 70%) si cateva mii de poze, m-am gandit serios la alternative de backup.</p>
<p>Am facut niste cautari serioase si am gasit cateva chestii interesante chiar la Google. In primul rand:</p>
<p><strong>Google Notebook</strong> &#8211; aparent e o banalitate&#8230; dar unde alt undeva poti stoca fisiere text, retete, bancuri, liste cu filme vazute, mini todo-uri ale proiectelor samd, daca nu chiar aici si chiar cu contul tau de gmail?</p>
<p><strong>Google Calendar</strong> &#8211; pentru cei care folosesc TODO&#8217;s dar si pentru cei care nu au folosit in viata lor, dar si-au impus o organizare mai buna in viata lor dezorganizata. Cel mai important aspect este ca primesti SMS-uri de la Google cu ce trebuie sa faci la ora cutare! Acum poti primi SMS inainte cu 1h sa pleci la munca/facultate/liceu/etc. Si cum romanul e al dracului de inventiv, de ce sa nu faci share la calendarul tau cu anumiti prieteni, si sa trimiti SMS-uri gratis, sub forma de task-uri?:D</p>
<p><strong>GSpace</strong> &#8211; oficial, cei care au facut acest add-on pentru Mozilla Firefox nu au nicio treaba cu cei de la Google. Ca sa fiu succint: prin intermediul acestui add-on te poti folosi de cei +7GB pe care ti-i ofera Gmail pentru a-ti stoca muzica, pozele, etc. Un alt avantaj este ca poti downloada fisierele uploadate prin intermediul Gspace, chiar din contul de Gmail pentru ca aceste fisiere sunt trimise ca email-uri. Singura problema pe care am intampinat-o a fost viteza de upload, cu care sper sa nu aveti prea mari probleme&#8230; dar chiar si asa, cine iti mai da GRATIS pe net acum +7GB ?!</p>
<p>P.S. in mod clar am renuntat la Gspace dat fiind uploadul si mi-am cumparat <a href="http://www.emag.ro/hard_disk-uri/hdd-samsung-320gb-sata2-7200rpm-16mb--pHD322IJ">aceasta jucarie</a> in varianta de 250GB <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  160RON si face toti banii (si ca sa fiu sigur ca microshit nu&#8217;si bate joc de mine si imi sterge ceva chiar si de pe hardul asta pe care il folosesc ca backup, ii scot alimentarea cat timp nu am nevoie de el)</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Create a pictures gallery with symfony in the admin]]></title>
<link>http://symfonyguide.wordpress.com/2009/08/18/create-a-pictures-gallery-with-symfony-in-the-admin/</link>
<pubDate>Tue, 18 Aug 2009 18:32:19 +0000</pubDate>
<dc:creator>Pierre Fournier</dc:creator>
<guid>http://symfonyguide.wordpress.com/2009/08/18/create-a-pictures-gallery-with-symfony-in-the-admin/</guid>
<description><![CDATA[I will try to explain the different steps to follow in order to create a pictures gallery related to]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I will try to explain the different steps to follow in order to create a pictures gallery related to let&#8217;s say an Event with Symfony.  We speak of a gallery since my Event can have several related pictures. I created this gallery in the backend but it could be easily transposed to any frontend. </p>
<p>Caveat: I use symfony 1.2 and Doctrine</p>
<p>Lets first have a glance at the problems I faced when trying to create the gallery:</p>
<ul>
<li>I wanted to display the <strong>Events as a list with their related pictures</strong> knowing that there was <strong>already a dedicated module in the backend to manage the Events</strong> properties</li>
<li>I wanted to be able to <strong>manage</strong> (erase, edit and add pictures)<strong> in a single form</strong> all the pictures related to my Event</li>
<li>I wanted to <strong>display the pictures as thumbnails</strong> in the list view</li>
</ul>
<p>And now the main steps we will follow to create our gallerie</p>
<ul>
<li>Create the picture class in our schema.yml</li>
<li>Generate a gallerie module based on Event class</li>
<li>Configure the generator in the backend</li>
<li>Create the BackendEventPicturesForm which will include all the related Pictures Form. We&#8217;ll had a specific widget to enable user to delete a picture</li>
<li>Create the BackendEmbedPictureForm and modify its method to handle file management in our directories</li>
<li>Install the thumbNailPlugin to generate associated thumbnails</li>
<li>Write a template to display the thumbnails</li>
</ul>
<p>So let&#8217;s begin with the schema.yml&#8230;<br />
You first have to create a <strong>Picture table that will be linked to the Event table with a 1 to Many</strong> relation.</p>
<pre>
#schema.yml
Picture:
  actAs: { Timestampable: ~ }
  columns:
    name: { type: string(255), unique: true, notnull: true }
    photo: { type: string(255), notnull: true }
    event_id: { type: integer, notnull: true }
    comment: { type: string(255) }
    deleted_at: { type: timestamp }
    is_visible: {type: boolean }
    tags: {type: string(255) }
  relations:
    Event: { local: event_id, foreign: id, foreignAlias: Pictures, onDelete: CASCADE, onUpdate: RESTRICT }
</pre>
<p>Notice that you don&#8217;t have to update the part of the schema.yml related to your Event class <em>since Doctrine will automatically link your Picture class with the event Class.</em></p>
<p>Then you have to generate a new module in the backend. As I already said, the Event class has already an event module. Since the list must based on our Events objects, we have to <strong>build the new module based on the Event class</strong>. Type the following in your terminal:</p>
<pre>
php symfony doctrine:generate-admin --module="gallerie" backend Event
</pre>
<p>This indicates symfony to create the gallerie module based on the Event class.<br />
Then go into the generator file of the new module</p>
<pre>
#apps/backend/modules/gallerie/config/generator.yml
generator:
  class: sfDoctrineGenerator
  param:
    model_class:                   Event
    theme:                            admin
    non_verbose_templates: true
    with_show:                     false
    singular:                         ~
    plural:                            ~
    route_prefix:                  event_gallerie
    with_doctrine_route:     1

    config:
      actions: ~
      fields:  ~
      list:
        title: Gallerie photo des Evènements
        table_method: retrieveBackendPicturesList
        display: [=name, _show_picture]
        fields:
          show_picture: {label: Dernières photos }
        object_actions:
          _edit: { label: Modifier la gallerie }
      filter:
        class: false
      form:
        class: BackendEventPicturesForm
      edit:    ~
      new:     ~
</pre>
<p>Take care to <strong>indicate in the config form part a dedicated form to use otherwise it will call the Event default form</strong>. The table_method allows to improve data requests efficiency by forcing symfony to automatically create a joint request between our Events and Pictures tables:</p>
<pre>
in lib/model/doctrine/EventTable.class.php
public function retrieveBackendPicturesList(Doctrine_Query $q)
  {
    $rootAlias = $q-&#62;getRootAlias();
    $q-&#62;leftJoin($rootAlias . '.Pictures p');
    return $q;
  }
</pre>
<p>We can now move to the next step dealing with forms creation. We need to use the very useful but not always clear embed form that allow the 1.2 version of Symfony. Embed forms are pretty straightforwards unless you try to upload files&#8230; which is the case here.</p>
<p>You first set up the dedicated form related to the Event class. We called it BackendEventPicturesForm in our generator. Creating a special form enables you to customize the form to your needs without interfeering with the form traditionnaly used to create a new Event.<br />
We will unset all the fields since we dont want to modify our Even and we will embed as many BackendEmbedPictureForm as the number of pictures related to our event plus a BackendEmbedPictureForm to add a new picture to our Event.</p>
<p>So let&#8217;s explain first how to build our BackendEmbedPictureForm. We will unset a couple of fields that are useless here (updated_at, created_at etc). What we really need is a name fied with a simple sfValidatorString. The file (called &#8216;photo&#8217; in our example) is much more tricky&#8230; We use a sfWidgetFormInputFileEditable to enter the file. The &#8216;file_src&#8217; indicate symfony where to look if a file already exists to display it (%file% in &#8216;template&#8217; option). The validator associated is the sfValidatorFile which will pass a &#8216;validatedFile&#8217; in the update method for instance. The &#8216;path&#8217; option indicates where the picture will be stored.</p>
<pre>
//in lib/model/form
class BackendEmbedPictureForm extends PictureForm
{
  public function configure()
  {
    $this-&#62;removeFields();
    $this-&#62;addWidgets();
    $this-&#62;addValidators();
  }

  public function removeFields(){
    unset(
    $this['event_id'],
    $this['deleted_at'],
    $this['created_at'],
    $this['updated_at']
    );
  }

  public function addWidgets(){
    $this-&#62;widgetSchema['name'] = new sfWidgetFormInput();
    $this-&#62;widgetSchema['photo'] = new sfWidgetFormInputFileEditable (array(
      'file_src'=&#62; sfConfig::get('app_dir_event_photos').$this-&#62;getObject()-&#62;getPhoto(),
      'is_image'=&#62; true,
      'edit_mode'=&#62;!$this-&#62;isNew(),
      'template'=&#62;/
<div>%file%/%input%/</div>

',
        ));
  }

  public function addValidators()
  {
    $this-&#62;validatorSchema['name'] = new sfValidatorString();
    $this-&#62;validatorSchema['photo'] = new sfValidatorFile(array(
     'path' =&#62; sfConfig::get('sf_web_dir') . sfConfig::get('app_dir_event_photos'),
     'required' =&#62; false,
     'mime_types' =&#62; 'web_images',
    ));
  }
}
</pre>
<p>Later on we will override a few methods of the form otherwise you will call me liyer since you wont have the expected results with this form. I used sfConfig::get(&#8216;app_dir_event_photos&#8217;) to set up in the config file of the app the end of the path to the directory.</p>
<p>Here is the code of the BackendEventPicturesForm. <em>To create a form based on an existing value, simply pass the name of the object to your form : newForm(myObjectToUpdate)</em>.</p>
<pre>
// in lib/model/form
class BackendEventPicturesForm extends EventForm
{
  public function configure()
  {
  	//unset all the event fields
  	$this-&#62;unsetAllExcept(array());

	  // embed forms only when editing
	  if (!$this-&#62;isNew()) {

	    if ($this-&#62;getObject()-&#62;getPictures())
	    {
		  	// embed all gallery pictures forms
		    foreach ($this-&#62;getObject()-&#62;getPictures() as $picture) {

			    // create a new subcategory form for the current subcategory model object
			    $picture_form = new BackendEmbedPictureForm($picture);

			    // embed the subcategory form in the main category form
			    $this-&#62;embedForm('picture'.$picture-&#62;getId(), $picture_form);

			    // set a custom label for the embedded form
			    $this-&#62;widgetSchema['picture'.$picture-&#62;getId()]-&#62;setLabel('Image: '.$picture-&#62;getName());

			    // set a custom widget to delete a picture
			    $this-&#62;widgetSchema['picture'.$picture-&#62;getId()]['name'] = new sfWidgetFormInputDelete(array(
			    'url' =&#62; 'event/deletePicture',      // required
			    'model_id' =&#62; $picture-&#62;getId(),        // required
			    'confirm' =&#62; 'Êtes-vous sûre de vouloir supprimer cette image de la gallerie ?',                     // optional
			    ));
		    }
	    }

		   //create a new picture form for a new picture model object
	    $picture_form = new BackendEmbedPictureForm();

		  // embed the picture form in the main Event form
		  $this-&#62;embedForm('picture', $picture_form);

		  // set a custom label for the embedded form
		  $this-&#62;widgetSchema['picture']-&#62;setLabel('Nouvelle Photo');

		  }

  }
}
</pre>
<p>I used a method which allows to unset all fields of a form except one. I found it on the following <a href="http://blog.adryjanek.eu/2008/12/12/symfony-12-sfform-yet-another-useful-function/"> article</a> but I write the code again since it was in a comment for Doctrine users</p>
<pre>
//in lib/form/doctrine
public function unsetAllExcept($keepFields = array())
  {
    foreach($this as $key =&#62; $value)
    {
      $baseFields[]=$key;
    }
    //array_diff compares two arrays and returns the difference
    $temp = array_diff($baseFields, $keepFields);

    foreach ($temp as $unsetField)
    {
      unset($this[$unsetField]);
    }
  }
</pre>
<p>If you went through the code, you might have noticed the <strong>sfWidgetFormInputDelete that enables the administrator to delete a picture</strong> from the gallery. I will show you the code in detail right now but I first give a few words of explanations on the options. The &#8216;url&#8217; will serve to indicate symfony where to find the executeDelete method (cf the routing system). the &#8216;model_id&#8217; could have been passed in the url since basically it will be added in the route. This widget is based on the code found in the following  <a href="http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator-part-2"> article </a> which I slightly modified.</p>
<pre>
// in lib

class sfWidgetFormInputDelete extends sfWidgetFormInput {

  protected function configure($options = array(), $attributes = array()) {

    $this-&#62;addRequiredOption('url');

    $this-&#62;addRequiredOption('model_id');

    $this-&#62;addOption('confirm', null);

    $this-&#62;addOption('icon', null);

    parent::configure($options, $attributes);
  }

  public function render($name, $value = null, $attributes = array(), $errors = array()) {

    $ctx = sfContext::getInstance();

    $request = $ctx-&#62;getRequest();

    $controller = $ctx-&#62;getController();

    if (is_null($this-&#62;getOption('confirm'))) {

      $this-&#62;setOption('confirm', __('Are you sure you want to delete this item?'));

    }

    if (is_null($this-&#62;getOption('icon'))) {

    	$this-&#62;setOption('icon', sprintf('http://%s%s/sfDoctrinePlugin/images/delete.png',$request-&#62;getHost(), $request-&#62;getRelativeUrlRoot()));

    } else {
      $this-&#62;setOption('icon', sprintf('http://%s%s/images/%s', $request-&#62;getHost(), $request-&#62;getRelativeUrlRoot(), $this-&#62;getOption('icon')));
    }

    $html = parent::render($name, $value, $attributes, $errors);

    $img = $this-&#62;renderTag('img', array('src' =&#62; $this-&#62;getOption('icon')));

    // this link was modifier by Pierre
    $link = link_to($img, $this-&#62;getOption('url') . '/?id=' . $this-&#62;getOption('model_id'), array('confirm' =&#62; 'Confirmez-vous ?'));
    //
    // it did not work before, placing an  'action' at the end of the url...
    //$link = '<a>genUrl($this-&#62;getOption('url')).'?id='.$this-&#62;getOption('model_id').'" onclick="if (confirm(\''.$this-&#62;getOption('confirm').'\')) { return true; };return false;"&#62;'.$img.'</a>';

    $html .= $link;

    return $html;

  }

}
</pre>
<p>And now, you have to <strong>add an executeDeletePicture method in the Event class</strong></p>
<pre>
//in apps/backend/modules/event/actions
public function executeDeletePicture (sfWebRequest $request)
  {
    $picture = Doctrine::getTable('Picture')-&#62;findById($request-&#62;getParameter('id'));
    $picture-&#62;delete();
    $this-&#62;redirect('@event_gallerie');
  }
</pre>
<p>But if you don&#8217;t override your bind method, you might be slightly disappointed.<strong> It seems Symfony does not handle automatically the file update process</strong>.<strong> More precisely, if you don&#8217;t bind these embedded forms, you won&#8217;t be able to access to some values</strong> of your embedded form&#8230; So you have to override the method bind()</p>
<pre>
//in lib/form/doctrine
public function bind(array $taintedValues = null, array $taintedFiles = null) {

    // remove the embedded new form if the name field was not provided)
    if (is_null($taintedValues['picture']['name']) &#124;&#124; strlen($taintedValues['picture']['name']) === 0 ) {

        unset($this-&#62;embeddedForms['picture'], $taintedValues['picture']);

        // pass the new form validations
        $this-&#62;validatorSchema['picture'] = new sfValidatorPass();

    } else {

        // set the category of the new subcategory form object
        $this-&#62;embeddedForms['picture']-&#62;getObject()-&#62;setEvent($this-&#62;getObject());

    }

    // call parent bind method
    $output = parent::bind($taintedValues, $taintedFiles);

    //forces symfony to bind the embedded form
	  foreach ($this-&#62;embeddedForms as $name =&#62; $form) {
	      $this-&#62;embeddedForms[$name]-&#62;isBound = true;
	      $this-&#62;embeddedForms[$name]-&#62;values = $this-&#62;values[$name];
	    }

    return $output;

  }
</pre>
<p>But then, we dont want symfony to save the uploaded file with a generated hexadecimal code which is unreadible&#8230; <strong>We want a nice file name like event-pictureName.fileExtension</strong>. First, we have to <strong>pass the form values to the save method</strong> so that we have a chance to rename the file ! When you upload a file, symfony will call the processUploadedFile method. This one will then call the save method, but with only 2 arguments. We&#8217;ll add a third argument (if not passed, symfony will try to access it but wont be able and will put a null value by default&#8230;) to be able to access to the &#8216;name&#8217; value of the form.</p>
<pre>
//in lib/form/doctrine BackendEventPicturesForm
//Saves the uploaded file for the given field
  protected function processUploadedFile($field, $filename = null, $values = null)
  {

  	parent::processUploadedFile($field, $filename = null, $values = null);

    //This line was added to be able to give a specific name to the registered file
    //by passing the $values[$field] to the "saveFile" method
    //otherwise you get an empty name for the file saved
    return $this-&#62;saveFile($field, $filename, $values[$field]);

  }
</pre>
<p>Now we&#8217;re done with the BackendEventPicturesForm, let&#8217;s complete the BackendEmbedPictureForm by overriding the updateObject() method. What we have to take into account by overriding is the management of the uploaded files in our directories (web/uploads/images/event-photos/). For instance, when a picture object is deleted, we want the associated file to be removed from its folder. Same when we edit the picture name we want to override the file name in the directory. And we must keep in mind that these actions will have to be duplicated to take care of the generated thumbnails&#8230; <strong>We could have overriden the save() method but the updateObject() stands for the kind of modifications we are doing </strong>: changing the linked properties of an object while the save() method will be more focused on our object and what we want to happen when saved.</p>
<pre>
//in lib/form/doctrine BackendEmbedPictureForm
public function updateObject($values = null)
  {
  	//define two "pathes variables" to ease code readibility
  	$eventPath = sfConfig::get('sf_web_dir') . sfConfig::get('app_dir_even_photos') ;
    $thumbPath = sfConfig::get('sf_web_dir') . sfConfig::get('app_dir_event_photos') . 'thumbnail/';

    //test if we are in edit mode (and not new mode)
    if(!$this-&#62;getObject()-&#62;isNew())
    {

      //check if object name has been changed by user
      if ($this-&#62;getValue('name') != $this-&#62;getObject()-&#62;getName())
      {

        //only the name has changed, the file remains the same
        if (!$this-&#62;getValue('photo'))
        {

        	//current associated picture filename has to be updated in our directories
          vac::renameFile(
            $eventPath . $this-&#62;getObject()-&#62;getPhoto(),
            $eventPath . $this-&#62;getNewPath()
          );

          //dont forget to update associated thumbnail filename
          vac::renameFile(
            $thumbPath . $this-&#62;getObject()-&#62;getPhoto(),
            $thumbPath . $this-&#62;getNewPath()
          );

          //related attribut of our picture has to be updated
          //we use getNewPath() method since the "generatePholoFileName()" method wont be called
          $this-&#62;getObject()-&#62;setPhoto($this-&#62;getNewPath());
        }

        //both name and picture file are changed
        else
        {
        	//previous picture file has to be deleted
          vac::deleteFile($eventPath . $this-&#62;getObject()-&#62;getPhoto());
          //associated thumbnail must be removed as well
          vac::deleteFile($thumbPath . $this-&#62;getObject()-&#62;getPhoto());

          //photo attribut of our picture is set to its new value
          $this-&#62;getObject()-&#62;setPhoto($this-&#62;getPicturePhotoName());
        }
      }
    }

    //creating a new picture for our event
    else
    {
    	//setting up the name of photo attribut
      $this-&#62;getObject()-&#62;setPhoto($this-&#62;getPicturePhotoName());
    }

    //back to the normal process of update (save object, etc, etc)
    $object = parent::updateObject($values);

    return $object;

  }
</pre>
<p>We call two methods that allegate the codes</p>
<pre>
// in BackendEmbedPictureForm
public function getPicturePhotoName()
  {
    return  vac::slugify($this-&#62;getValue('name')) . $this-&#62;getValue('photo')-&#62;getOriginalExtension();
  }
</pre>
<p>and the second one which is a bit more tricky and enables to collect the file extension of our file before renaming it (and then we can once again add this extension to our new name) when the user changes only the name (and leaves the file unchanged)</p>
<pre>
// in BackendEmbedPictureForm
public function getNewPath()
  {
  	//Collect photo's file type
    $array = explode(".", $this-&#62;getObject()-&#62;getPhoto());
    //rename photo and add file type
    return $this-&#62;getObject()-&#62;getEvent()-&#62;getSlugName() . '-' . vac::slugify($this-&#62;getValue('name')) . '.' . $array[1];

  }
</pre>
<p>We are almost done. There only remains to add a few methods to the Picture class. You can see that we refer to the thumbnails. Before explaining the process to generate the thumbnail, lets open a paranthesis. We added to the Picture class the following method :</p>
<pre>
//Customize the generated picture file name
  public function generatePhotoFileName (sfValidatedFile $file)
  {
  	return $this-&#62;getEvent()-&#62;getSlugName().'-'.$this-&#62;getPhoto();
  }
</pre>
<p>If you don&#8217;t do this, you will get very sad when you will see under which name symfony registers your file. This method is called automatically by the save method. The argument sfValidatedFile has been generated by the sfFileValidator</p>
<p>Let&#8217;s finish with the thumbnails. Symfony has a plugin that takes care of everything for you. Just type into your terminal</p>
<pre>
php symfony plugin:install sfThumbnailPlugin
</pre>
<p>Now, we need to generate a thumbnail each time a file is uploaded or modified. That&#8217;s why we&#8217;ll override the save() method and add a generateThumbnail() instruction</p>
<pre>
// in Picture.Class.php
//save method is overrided to create a thumbnail when picture saved
  public function save(Doctrine_Connection $conn = null)
  {
  	//check if object has been modified
    if ($this-&#62;isModified())
    {
    	//generate associated thumbnail
  	  $this-&#62;generateThumbnail();
    }

    return parent::save($conn);
  }
</pre>
<p>Since we dont want to generate a thumbnail for all our Pictures each time we press the &#8217;save&#8217; button, we check if the object has been modified before generating a thumbnail. Now let&#8217;s generate the thumbnail. This is pretty straightforward with the plugin. Just create the thumbnail file or you will have an error message</p>
<pre>
//Generate a thumbnail in upload dir under png format
	public function generateThumbnail()
	{
	   //set path variable to ease readibility of code
	   $uploadDir = sfConfig::get('sf_web_dir') . sfConfig::get('app_dir_event_photos');

	   //create new thumbnail
		 $thumbnail = new sfThumbnail(100, 100);
		 //get the file the thumbnail will be based on
		 $thumbnail-&#62;loadFile($uploadDir.'/'.$this-&#62;getPhoto());
		 //save the thumbnail in the indicated directory
		 $thumbnail-&#62;save($uploadDir.'/thumbnail/'. $this-&#62;getPhoto());
	}
</pre>
<p>And finally we override the delete() method to erase the files in the directory when &#8220;delete&#8221; is pressed on the widget we added to our pictures in the form</p>
<pre>
//overriden to delete the file from the upload/Event-photo folder
	public function delete(Doctrine_Connection $conn = null){
		//delete picture file in the directory
		vac::deleteFile( sfConfig::get('sf_web_dir') . sfConfig::get('app_dir_event_photos') . $this-&#62;getPhoto());
		//delete associated thumbnail file in the directory
    vac::deleteFile( sfConfig::get('sf_web_dir') . sfConfig::get('app_dir_event_photos') . 'thumbnail/' . $this-&#62;getPhoto());

    //return to normal method
		parent::delete($conn);
	}
</pre>
<p>I was about to forget the template to display the thumbnail ! Here it is :</p>
<pre>
// in apps/backend/modules/gallerie/templates/ _show_picture
//dont forget to add php tags...
foreach ($event-&#62;getPictures() as $picture):
  if ($picture-&#62;getIsVisible()):
    echo image_tag(sfConfig::get('app_dir_event_photos').'thumbnail/'.$picture-&#62;getPhoto() );
  endif;
endforeach;
</pre>
<p>And that&#8217;s it ! Hope this has been useful. A few methods are not explained (slugify or delete) but you will find equivalent easily on the net.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[WCF over HTTPS]]></title>
<link>http://cgeers.wordpress.com/2009/08/07/wcf-over-https/</link>
<pubDate>Fri, 07 Aug 2009 13:54:53 +0000</pubDate>
<dc:creator>Christophe</dc:creator>
<guid>http://cgeers.wordpress.com/2009/08/07/wcf-over-https/</guid>
<description><![CDATA[Introduction A couple of weeks ago I was asked to write a web service that needed to provide a singl]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a title="introduction" name="introduction"></a><strong>Introduction</strong><img class="alignnone size-medium wp-image-24 alignright" style="float:right;" src="http://cgeers.wordpress.com/files/2008/04/dotnetwcf.gif" alt="" width="80" height="80" /></p>
<p>A couple of weeks ago I was asked to write a web service that needed to provide a single operation (method) that allowed the user to upload a file using a Secure Sockets Layer (SSL / HTTPS) .</p>
<p>Although they changed their minds and went for a solution using a VPN connection, I still decided to create the web service in case they went back on their decision again.</p>
<p>This article outlines the steps you need to follow in order to create a service to upload a file over HTTPS using WCF. And it&#8217;s been quite a while since I wrote my last article for this blog. I figured this would make an interesting topic&#8230;</p>
<p><!--more--></p>
<p><a title="top" name="top"></a><strong>Table Of Contents</strong></p>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#servicecontract">WCF Service Contract</a></li>
<li><a href="#serviceimplementation">Service Implementation</a></li>
<li><a href="#servicehost">Hosting The Service</a></li>
<li><a href="#configuration">Configuring The Host</a></li>
<li><a href="#ssl">SSL Certificate</a></li>
<li><a href="#client">Client Application</a></li>
<li><a href="#authenticateserver">Authenticate The Server</a></li>
<li><a href="#authenticateclient">Authenticate The Client</a></li>
<li><a href="#summary">Summary</a></li>
<li><a href="#download">Download</a></li>
</ul>
<p><a title="servicecontract" name="servicecontract"></a><strong>WCF Service Contract</strong></p>
<p>Let&#8217;s start by laying the groundwork for the WCF Service. As stated the service must enable users to upload a file to the web server which hosts it. Thus the resulting service contract only contains one method, aptly named Upload(&#8230;).</p>
<p>Start by opening up Visual Studio 2008 and create a new blank solution called WcfOverHttps. Next add a new WCF Service Library titled CGeers.Wcf.Services. This class library contains some automatically generated files (IService1.cs, Service.cs, App.config). Rename the IService.cs file to IFileUploadService.cs.</p>
<p><strong>Figure 1</strong> &#8211; Solution Explorer</p>
<p><a href="http://cgeers.wordpress.com/files/2009/08/solutionexplorer1.jpg"><img class="aligncenter size-full wp-image-698" title="Solution Explorer" src="http://cgeers.wordpress.com/files/2009/08/solutionexplorer1.jpg" alt="Solution Explorer" width="196" height="148" /></a></p>
<p>The code for the service contract is displayed in Listing 1:</p>
<p><strong>Listing 1</strong> &#8211; Service Contract</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>[ServiceContract(Namespace = <span class="str">"http://cgeers.wordpress.com/wcf/services"</span>)]
<span class="kwrd">public</span> <span class="kwrd">interface</span> IFileUploadService
{
    [OperationContract]
    FileReceivedInfo Upload(FileInfo fileInfo);
}</pre>
</div>
<p>As you can see displayed in Figure 1 and Listing 1 above they mention two other classes, namely:</p>
<ol>
<li>FileInfo</li>
<li>FileReceivedInfo</li>
</ol>
<p>These classes are both decorated with the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.messagecontractattribute.aspx" target="_blank">MessageContract</a> attribute. To upload the file I opted to use streaming. WCF stipulates that the parameter that holds the data to be streamed must be the only parameter in the method.</p>
<p>You could opt to change the type of the fileInfo parameter to Stream, but then you cannot send any additional information about the file along with it. You can circumvent this issue by creating a new class which contains all of the information you want to transmit. By decorating this class with the MessageContract attribute you can use this class (or message) as a parameter or return type in your service operations.</p>
<p>The FileInfo class specifies the structure of a SOAP envelope for a particular message.</p>
<p><strong>Listing 2</strong> &#8211; FileInfo class</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>[MessageContract]
<span class="kwrd">public</span> <span class="kwrd">class</span> FileInfo
{
    [MessageHeader(MustUnderstand = <span class="kwrd">true</span>)]
    <span class="kwrd">public</span> <span class="kwrd">string</span> FileName { get; set; }

    [MessageHeader(MustUnderstand = <span class="kwrd">true</span>)]
    <span class="kwrd">public</span> <span class="kwrd">long</span> Length { get; set; }

    [MessageBodyMember(Order = 1)]
    <span class="kwrd">public</span> Stream Stream { get; set; }
}</pre>
</div>
<p>As you can see in Listing 2 the FileInfo class contains three properties. Apart from the actual file (Stream property) the filename and length of the file are also provided.</p>
<p>By applying the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.messageheaderattribute.aspx" target="_blank">MessageHeader attribute</a> to the FileName and Length propery you place this information in the header of the SOAP message. When streaming a file the body of the SOAP message must only contain the actual file itself. By applying the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.messagebodymemberattribute.aspx" target="_blank">MessageBodyMember attribute</a> to the Stream property you place it in the body of the SOAP message.</p>
<p>If your service operation contains a parameter of a type which has been decorated with the MessageContract attribute then all of the parameters and the return type used in this operation must be of a type to which this attribute has been applied.</p>
<p>You cannot mix parameters of a primitive type with message contracts. For instance if you want the Upload(&#8230;) method to return a boolean indicating if the upload succeeded or failed then you have to wrap this in another message contract.</p>
<p>Listing 3 displays how to setup the return value as a message contract. Apart from the boolean value (body) the header of this SOAP message contains the filename of the uploaded file and an optional message property which contains some information about why the upload failed.</p>
<p><strong>Listing 3</strong> &#8211; FileReceivedInfo class</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>[MessageContract]
<span class="kwrd">public</span> <span class="kwrd">class</span> FileReceivedInfo
{
    [MessageHeader(MustUnderstand = <span class="kwrd">true</span>)]
    <span class="kwrd">public</span> <span class="kwrd">string</span> FileName { get; set; }

    [MessageHeader(MustUnderstand = <span class="kwrd">true</span>)]
    <span class="kwrd">public</span> <span class="kwrd">string</span> Message { get; set; }

    [MessageBodyMember(Order = 1)]
    <span class="kwrd">public</span> <span class="kwrd">bool</span> UploadSucceeded { get; set; }
}</pre>
</div>
<p>If you try to mix message contracts and parameters of a primitive type you&#8217;ll receive the following error message:</p>
<p><em>System.InvalidOperationException: The operation &#8216;Method&#8217; could not be loaded because it has a parameter or return type of type System.ServiceModel.Channels.Message or a type that has MessageContractAttribute and other parameters of different types. When using System.ServiceModel.Channels.Message or types with MessageContractAttribute, the method must not use any other types of parameters.</em></p>
<p><a href="#top">Top of page</a></p>
<p><a title="serviceimplementation" name="serviceimplementation"></a><strong>Service Implementation</strong></p>
<p>Now that the contract for the service has been established it&#8217;s time to provide an actual implementation for it.</p>
<p>Start by renaming the Service1.cs file to FileUploadService.cs and add a reference to the System.Configuration assembly.</p>
<p>Listing 4 displays the code for implementing the service. The code is pretty straightforward. Check out the comments in the code for more explanation. Basically it reads the incoming stream and saves it to a file using familiar .NET code.</p>
<p>The Upload(&#8230;) method&#8217;s return type is of the FileReceivedInfo type. If the upload succeeds the UploadSucceeded property is set to true, if it fails this property is set to false and the message property is populated with the message property of the exception that occured.</p>
<p><strong>Listing 4</strong> &#8211; Service Implementation</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
    ConcurrencyMode = ConcurrencyMode.Single)]
<span class="kwrd">public</span> <span class="kwrd">class</span> FileUploadService : IFileUploadService
{
    <span class="preproc">#region</span> IFileUploadService Members

    <span class="kwrd">public</span> FileReceivedInfo Upload(FileInfo fileInfo)
    {
        <span class="kwrd">try</span>
        {
            <span class="rem">// Determine to which directory the file needs to be uploaded</span>
            <span class="kwrd">string</span> uploadDirectory =
                ConfigurationManager.AppSettings[<span class="str">"uploadDirectory"</span>];
            <span class="kwrd">if</span> (String.IsNullOrEmpty(uploadDirectory))
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> InvalidOperationException(<span class="str">"..."</span>);
            }

            <span class="rem">// Try to create the upload directory if it does not yet exist</span>
            <span class="kwrd">if</span> (!Directory.Exists(uploadDirectory))
            {
                Directory.CreateDirectory(uploadDirectory);
            }

            <span class="rem">// Check if a file with the same filename is already </span>
            <span class="rem">// present in the upload directory. If this is the case </span>
            <span class="rem">// then delete this file</span>
            <span class="kwrd">string</span> path = Path.Combine(uploadDirectory, fileInfo.FileName);
            <span class="kwrd">if</span> (File.Exists(path))
            {
                <span class="rem">// Check if the file is read-only</span>
                <span class="kwrd">if</span> ((File.GetAttributes(path) &#38; FileAttributes.ReadOnly) ==
                    FileAttributes.ReadOnly)
                {
                    File.SetAttributes(path, FileAttributes.Normal);
                }
                File.Delete(path);
            }

            <span class="rem">// Read the incoming stream and save it to file</span>
            <span class="kwrd">const</span> <span class="kwrd">int</span> bufferSize = 2048;
            <span class="kwrd">byte</span>[] buffer = <span class="kwrd">new</span> <span class="kwrd">byte</span>[bufferSize];
            <span class="kwrd">using</span> (FileStream outputStream = <span class="kwrd">new</span> FileStream(path,
                FileMode.Create, FileAccess.Write))
            {
                <span class="kwrd">int</span> bytesRead = fileInfo.Stream.Read(buffer, 0, bufferSize);
                <span class="kwrd">while</span> (bytesRead &#62; 0)
                {
                    outputStream.Write(buffer, 0, bytesRead);
                    bytesRead = fileInfo.Stream.Read(buffer, 0, bufferSize);
                }
                outputStream.Close();
            }
            <span class="kwrd">return</span> <span class="kwrd">new</span> FileReceivedInfo
                       {
                           FileName = fileInfo.FileName,
                           Message = String.Empty,
                           UploadSucceeded = <span class="kwrd">true</span>
                       };
        }
        <span class="kwrd">catch</span> (Exception ex)
        {
            <span class="kwrd">return</span> <span class="kwrd">new</span> FileReceivedInfo
                       {
                           FileName = fileInfo.FileName,
                           Message = ex.Message,
                           UploadSucceeded = <span class="kwrd">false</span>
                       };
        }
    }

    <span class="preproc">#endregion</span>
}</pre>
</div>
<p><a href="#top">Top of page</a></p>
<p><a title="servicehost" name="servicehost"></a><strong>Hosting The Service</strong></p>
<p>Now that the service has been setup it&#8217;s time to create a host for it. To keep things simple a console application will do. Add a new Console Application project to your solution named ConsoleHost. Next add references to the System.ServiceModel assembly and the CGeers.Wcf.Services project.</p>
<p>The code for the Main(&#8230;) method of the console application is slim and simple. Take a look at Listing 5.</p>
<p><strong>Listing 5</strong> &#8211; Hosting the FileUpload service</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre><span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)
{
    ServiceHost host = <span class="kwrd">new</span> ServiceHost(<span class="kwrd">typeof</span>(FileUploadService));
    host.Open();
    Console.WriteLine(<span class="str">"FileUpload Service Host"</span>);
    Console.WriteLine(<span class="str">"Service Started!"</span>);
    <span class="kwrd">foreach</span> (Uri address <span class="kwrd">in</span> host.BaseAddresses)
    {
        Console.WriteLine(<span class="str">"Listening on "</span> + address);
    }
    Console.WriteLine(<span class="str">"Press any key to close the host..."</span>);
    Console.ReadKey();
    host.Close();
}</pre>
</div>
<p>A new ServiceHost instance is created for the FileUploadService type and the host is then started. But before you launch the console application you still need to configure the service. Instead of doing this through code I opted to do this via an application configuration file. The next section addresses how you can easily configure your service.</p>
<p><a href="#top">Top of page</a></p>
<p><a title="configuration" name="configuration"></a><strong>Configuring The Host</strong></p>
<p>Start by adding an application configuration (App.config) file to the ConsoleHost project. Next specify the directory in which the service should save the incoming files.</p>
<p><strong>Listing 6</strong> &#8211; Upload directory</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>&#60;appSettings&#62;
  &#60;add key=<span class="str">"uploadDirectory"</span> <span class="kwrd">value</span>=<span class="str">"C:\temp\upload"</span> /&#62;
&#60;/appSettings&#62;</pre>
</div>
<p>Now add a node to the configuration file. Within this node three child nodes will be added in order to configure the service. The first such node specifies the service&#8217;s behavior.</p>
<p><strong>Listing 7</strong> &#8211; Service Behavior</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>&#60;behaviors&#62;
  &#60;serviceBehaviors&#62;
    &#60;behavior name=<span class="str">"FileUploadServiceBehavior"</span>&#62;
      &#60;serviceMetadata httpGetEnabled=<span class="str">"False"</span> httpsGetEnabled=<span class="str">"True"</span> /&#62;
      &#60;serviceDebug includeExceptionDetailInFaults=<span class="str">"False"</span> /&#62;
    &#60;/behavior&#62;
  &#60;/serviceBehaviors&#62;
&#60;/behaviors&#62;</pre>
</div>
<p>The behavior specifies that the service should not propagate exception details and that it&#8217;s metadata should be shared over HTTPS (httpsGetEnabled) instead of HTTP (httpGetEnabled).</p>
<p>Next up is the binding for the service. Since the goal is to use HTTPS the built-in BasicHttpBinding fits the bill. A couple of its properties need to be tweaked to fit the needs of the service, namely:</p>
<ol>
<li><strong>transferMode</strong>: Set it to Streamed to enable streaming.</li>
<li><strong>messageEncoding</strong>: The message encoding is set to <a href="http://msdn.microsoft.com/en-us/library/aa395209.aspx" target="_blank">MTOM encoding</a> which is a mechanism for transmitting binary attachements with SOAP messages.</li>
<li><strong>maxReceivedMessageSize</strong>: Set to 64 megabytes to allow large files to be uploaded.</li>
<li><strong>maxBufferSize</strong>: Set to 64 kilobytes.</li>
<li><strong>receiveTimeout</strong>: Set to 10 minutes. If the file fails to upload within this time frame an exception will be thrown.</li>
</ol>
<p><strong>Remark</strong>: Configure these settings according to the needs of your application. For my application a maximum of 64 Mb for the file size and 64 KB for the buffer are sufficient.</p>
<p><strong>Listing 8</strong> &#8211; The Binding</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>&#60;bindings&#62;
  &#60;basicHttpBinding&#62;
    &#60;!-- buffer: 64KB; max size: 64MB --&#62;
    &#60;binding name=<span class="str">"FileUploadServiceBinding"</span>
             transferMode=<span class="str">"Streamed"</span>
             messageEncoding=<span class="str">"Mtom"</span>
             maxReceivedMessageSize=<span class="str">"67108864"</span> maxBufferSize=<span class="str">"65536"</span>
             closeTimeout=<span class="str">"00:01:00"</span> openTimeout=<span class="str">"00:01:00"</span>
             receiveTimeout=<span class="str">"00:10:00"</span> sendTimeout=<span class="str">"00:01:00"</span>&#62;
      &#60;security mode=<span class="str">"Transport"</span>&#62;
        &#60;transport clientCredentialType=<span class="str">"None"</span> /&#62;
      &#60;/security&#62;
    &#60;/binding&#62;
  &#60;/basicHttpBinding&#62;
&#60;/bindings&#62;</pre>
</div>
<p>Last but not least is the configuration for the service itself.</p>
<p><strong>Listing 9</strong>: FileUploadService configuration</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>&#60;services&#62;
  &#60;service behaviorConfiguration=<span class="str">"FileUploadServiceBehavior"</span>
    name=<span class="str">"CGeers.Wcf.Services.FileUploadService"</span>&#62;
    &#60;endpoint address=<span class="str">""</span> binding=<span class="str">"basicHttpBinding"</span> contract=<span class="str">"CGeers.Wcf.Services.IFileUploadService"</span>
              bindingConfiguration=<span class="str">"FileUploadServiceBinding"</span>&#62;
      &#60;identity&#62;
        &#60;dns <span class="kwrd">value</span>=<span class="str">"localhost"</span> /&#62;
      &#60;/identity&#62;
    &#60;/endpoint&#62;
    &#60;endpoint address=<span class="str">"mex"</span> binding=<span class="str">"mexHttpsBinding"</span> contract=<span class="str">"IMetadataExchange"</span> /&#62;
    &#60;host&#62;
      &#60;baseAddresses&#62;
        &#60;add baseAddress=<span class="str">"https://127.0.0.1:8741/FileUploadService/"</span> /&#62;
      &#60;/baseAddresses&#62;
    &#60;/host&#62;
  &#60;/service&#62;
&#60;/services&#62;</pre>
</div>
<p>The service&#8217;s ABC&#8217;s are specified and it&#8217;s hooked up to the behavior and binding we configured earlier. The address https://127.0.0.1:8741/FileUploadService/ is specified as being the location of the service. As you can see in the service&#8217;s binding the security is set to Transport which requires that you provide an HTTPS based address.</p>
<p><strong>Remark</strong>: Note that for the metadata exchange (mex) the mexHttpsBinding is specified and not the default mexHttpBinding.</p>
<p>If you run the ConsoleHost project now you receive the following result:</p>
<p><strong>Figure 2</strong> &#8211; ConsoleHost<br />
<a href="http://cgeers.wordpress.com/files/2009/08/consolehost.jpg"><img class="aligncenter size-full wp-image-732" title="Console Host" src="http://cgeers.wordpress.com/files/2009/08/consolehost.jpg" alt="Console Host" width="476" height="131" /></a></p>
<p><a href="#top">Top of page</a></p>
<p><a title="ssl" name="ssl"></a><strong>SSL Certificate</strong></p>
<p>If you run the ConsoleHost project now and enter the address https://127.0.0.1:8741/FileUploadService/ in a browser you&#8217;ll receive an error. Before you can proceed , you need to bind an SSL Certificate to port 8741 for the IP address 127.0.0.1.</p>
<p>First you need to create an SSL certificate. You can do this using the makecert.exe command-line utility. Just start a new Visual Studio command prompt and enter the following command in order to create a X509 certificate which will be used for SSL communication on the localhost (127.0.0.1).</p>
<p>makecert.exe -sr LocalMachine -ss My -n CN=127.0.0.1 -sky exchange -sk -pe</p>
<p>After this command is executed, the new certificate with the private key is created and stored in the LocalMachine Personal store. To see it, use the MMC-certificate snap-in.</p>
<p>After executing this command your new certificate is created and stored in the LocalMachine Personal store. Open the MMC-certificate snap-in to see it.</p>
<ol>
<li>Click Start, Run and enter the command &#8220;mmc&#8221;</li>
<li>Click OK to start the MMC console</li>
<li>Click File &#124; Add/Remove snap-in&#8230;</li>
<li>In the resulting dialog that pops up click the Add option and choose the Certificates snap-in</li>
<li>Confirm your changes by closing the dialog windows</li>
</ol>
<p>Afterwards you can view you new certificate in the MMC console as displayed in Figure 3.</p>
<p><strong>Figure 3</strong> &#8211; MMC Console Certificates snap-in<br />
<a href="http://cgeers.wordpress.com/files/2009/08/mmc.jpg"><img class="aligncenter size-medium wp-image-740" title="MMC Console Certificates Snap-in" src="http://cgeers.wordpress.com/files/2009/08/mmc.jpg?w=300" alt="MMC Console Certificates Snap-in" width="300" height="187" /></a></p>
<p>Next you need to bind this new certificate to the port 8741. Return to the Visual Studio command prompt and enter the following command to do so:</p>
<p>httpcfg.exe set ssl -i 127.0.0.1:8741 -h cfdf5d1140b94614d047dd77c7bd4d4d4422e1c9 -Personal</p>
<p>Replace the &#8220;cfdf5d1140b94614d047dd77c7bd4d4d4422e1c9&#8243; value with the thumbprint of your own certificate. You can retrieve the thumbprint using the Certificates MMC snap-in as shown in Figure 3. Be sure to remove all the spaces.</p>
<p>If you rerun the ConsoleHost application after creating the certificate and binding it to 127.0.0.1:8741 you should receive the standard WCF service test page after entering the address https://127.0.0.1:8741/FileUploadService/ in a browser.</p>
<p><strong>Figure 4</strong> &#8211; FileUploadService<br />
<a href="http://cgeers.wordpress.com/files/2009/08/fileuploadservice.jpg"><img src="http://cgeers.wordpress.com/files/2009/08/fileuploadservice.jpg?w=300" alt="FileUploadService" title="FileUploadService" width="300" height="255" class="aligncenter size-medium wp-image-747" /></a></p>
<p><a href="#top">Top of page</a></p>
<p><a title="client" name="client"></a><strong>Client Application</strong></p>
<p>Voila, now that the file upload service is ready we can begin to consume it. Let&#8217;s test this&#8230;</p>
<p>Add a new console application project named ConsoleClient to your solution. Next add a reference to the System.ServiceModel assembly. When done start the ConsoleHost application in non-debug mode. We need to add a reference to this service to the client application. For this the service needs to be up and running.</p>
<p>Right click on the ConsoleClient project within the Solution Explorer and choose &#8220;Add Service Reference&#8230;&#8221;. The Add Service Reference dialog is displayed. Enter the address of the service (https://127.0.0.1:8741/FileUploadService/) in the address field and click Go. The SSL certificate will be presented to the calling application (= Visual Studio). You&#8217;ll be prompted to accept the certificate. Click Yes to proceed.</p>
<p><strong>Figure 5</strong> &#8211; SSL Certificate Security Alert In Visual Studio 2008<br />
<a href="http://cgeers.wordpress.com/files/2009/08/ssl-certificate-security-al.jpg"><img src="http://cgeers.wordpress.com/files/2009/08/ssl-certificate-security-al.jpg?w=300" alt="SSL Certificate Security Alert" title="SSL Certificate Security Alert" width="300" height="235" class="aligncenter size-medium wp-image-755" /></a></p>
<p>Rename the namespace ServiceReference1 to ServiceReferences and click Advanced. The Service Reference Settings dialog is shown. Make sure that the option &#8220;Always generate message contracts&#8221; is checked. Click OK to close this dialog. Click OK once more to let Visual Studio add the service reference and generate the necessary proxy classes.</p>
<p><strong>Remark</strong>: If you don&#8217;t check the option &#8220;Always generate message contracts&#8221; then the message contract&#8217;s properties will appear as individual parameters in the proxy. And for the result type you&#8217;ll only get the property that is marked as the body of the SOAP message.</p>
<p>Unchecked the Upload(&#8230;) method on the proxy will be generated as such:</p>
<p><strong>Listing 10</strong>: Always Generate Message Contracts</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
<span class="kwrd">bool</span> Upload(<span class="kwrd">string</span> fileName, <span class="kwrd">long</span> length, Stream stream);
</pre>
</div>
<p>instead of</p>
<div class="csharpcode"><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
FileReceivedInfo Upload(FileInfo fileInfo);</pre>
</div>
<p>Once the necessary proxy classes have been generated consuming the service is an easy task. Consider the following code in the Main(&#8230;) method of the ConsoleClient application.</p>
<p><strong>Listing 11</strong> &#8211; ConsoleClient Application</p>
<div class="csharpcode">
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
<span class="kwrd">using</span> (FileUploadServiceClient proxy = <span class="kwrd">new</span> FileUploadServiceClient())
{
    FileStream inputStream = File.Open(@"c:\temp\uploadtest.txt", FileMode.Open);

    ServiceReferences.FileInfo fileInfo =
        <span class="kwrd">new</span> ServiceReferences.FileInfo("uploaded.txt", inputStream.Length, inputStream);
    FileReceivedInfo info = proxy.Upload(fileInfo);
    <span class="kwrd">if</span> (info.UploadSucceeded)
    {
        Console.WriteLine(String.Format(<span class="str">"File {0} uploaded"</span>, info.FileName));
    }
    <span class="kwrd">else</span>
    {
        Console.WriteLine(String.Format(<span class="str">"File {0} upload failed"</span>, info.FileName));
        Console.WriteLine(info.Message);
    }
    Console.WriteLine();
    Console.ReadLine();
}</pre>
</div>
<p><a href="#top">Top of page</a></p>
<p><a title="authenticateserver" name="authenticateserver"></a><strong>Authenticate The Server</strong></p>
<p>Make sure the ConsoleHost application is still running and start the ConsoleClient application for the first time. Upon hitting the line of code that calls the Upload(&#8230;) method on the proxy you&#8217;ll receive the following error message:</p>
<p><em>Could not establish trust relationship for the SSL/TLS secure channel with authority &#8216;127.0.0.1:8741&#8242;.</em></p>
<p>This means that the server (ConsoleHost) presented the SSL certificate to the client application during the handshake and the client did not validate it. Thus a trusted relationship for the SSL/TLS secure channel could not be established.</p>
<p>To solve this problem add the following code to the beginning of the Main(&#8230;) method of the ConsoleClient application.</p>
<p><strong>Listing 12</strong> &#8211; Validating The Server</p>
<div class="csharpcode">
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation;</pre>
</div>
<p>The code for the customXertificateValidation(&#8230;) method is as follows:</p>
<div class="csharpcode">
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> customXertificateValidation(<span class="kwrd">object</span> sender, X509Certificate cert,
    X509Chain chain, SslPolicyErrors error)
{
    X509Certificate2 certificate = (X509Certificate2)cert;
    <span class="kwrd">if</span> (certificate.Subject == <span class="str">"CN=127.0.0.1"</span> &#38;&#38; !String.IsNullOrEmpty(certificate.Thumbprint) &#38;&#38;
        certificate.Thumbprint.ToLower() == <span class="str">"cfdf5d1140b94614d047dd77c7bd4d4d4422e1c9"</span>)
    {
        <span class="kwrd">return</span> <span class="kwrd">true</span>;
    }
    <span class="kwrd">return</span> <span class="kwrd">false</span>;
}</pre>
</div>
<p>When the customXertificateValidation(&#8230;) method is called (callback) by WCF to validate the server certificate you have the opportunity to inspect the certificate (= cert parameter). In this example the value of the Subject and Thumbprint are checked in order to validate the identity of the server. If they match then the server is authenticated, if not then the SSL connection cannot be established.</p>
<p><strong>Remark</strong>: Feel free to adjust the validation of the SSL certificate to suit your own needs.</p>
<p>Upon running the client again after applying these changes you&#8217;ll receive the message &#8220;File uploaded.txt uploaded&#8221;.</p>
<p><a href="#top">Top of page</a></p>
<p><a title="authenticateclient" name="authenticateclient"></a><strong>Authenticate The Client</strong></p>
<p>At this point you could consider your file upload service complete, but one crucial item remains. Namely authenticating the client by the server. </p>
<p>I don&#8217;t want anyone who happens to stumble upon my service to be able to upload files to the web server. To block unauthorized users we have to validate the client. Luckily WCF allows you do so  without much hassle.</p>
<p>Let&#8217;s return to the CGeers.Wcf.Service project for a while. Add a reference to the System.IdentityModel assembly and add a new class called CustomUserNameValidator. </p>
<p><strong>Listing 13</strong> &#8211; CustomUserNameValidator</p>
<div class="csharpcode">
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
<span class="kwrd">public</span> <span class="kwrd">class</span> CustomUserNameValidator : UserNamePasswordValidator
{
    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Validate(<span class="kwrd">string</span> userName, <span class="kwrd">string</span> password)
    {
        <span class="kwrd">if</span> (userName != <span class="str">"Christophe"</span> &#124;&#124; password != <span class="str">"WCFRocks!"</span>)
        {
            <span class="rem">// This throws an informative fault to the client.</span>
            <span class="kwrd">throw</span> <span class="kwrd">new</span> FaultException(<span class="str">"Incorrect username or password"</span>);
        }
    }
}</pre>
</div>
<p>This class derives from the UserNamePasswordValidator which can be found in the System.IdentityModel.Selectors namespace. Only one method needs to be overriden, namely the Validate(&#8230;) method. Here you need to specify your own custom code in order to validate the provided username and password. Just throw a FaultException if you cannot validate the user.</p>
<p>Next you need to configure the ConsoleHost application so that it uses the CustomUserNameValidator class in order to validate the clients. Open the App.config file of the ConsoleHost application and adjust the following settings:</p>
<p>For the basicHttpBinding set the required clientCredentialType of the transport security to Basic. This requires that the client present the necessary credentials (username &#38; password).</p>
<p><strong>Listing 14</strong> &#8211; Adjusting The Binding</p>
<div class="csharpcode">
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
...
&#60;security mode=<span class="str">"Transport"</span>&#62;
  &#60;transport clientCredentialType=<span class="str">"Basic"</span> /&#62;
&#60;/security&#62;
...</pre>
</div>
<p>Then add the following bit of configuration to the service behavior to tell the service how to validate the client credentials.</p>
<p><strong>Listing 15</strong> &#8211; Adjusting The Service Behavior</p>
<div class="csharpcode">
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
...
&#60;serviceCredentials&#62;
  &#60;userNameAuthentication
    userNamePasswordValidationMode=<span class="str">"Custom"</span>
    customUserNamePasswordValidatorType=<span class="str">"CGeers.Wcf.Services.CustomUserNameValidator, CGeers.Wcf.Services"</span> /&#62;
&#60;/serviceCredentials&#62;
...  </pre>
</div>
<p>The service is now correctly setup and requires the client to provide the necessary credentials. If you run the ConsoleClient application now you&#8217;ll receive the following error message:</p>
<p><em>The HTTP request is unauthorized with client authentication scheme &#8216;Anonymous&#8217;. The authentication header received from the server was &#8216;Basic realm=&#8221;"&#8216;.</em></p>
<p>The configuration for the client application needs to reflect the changes we made to the service. Right click on the service reference and choose &#8220;Update Service Reference&#8221;.</p>
<p>Running the client application again will now result in the following error message:</p>
<p><em>The HTTP request was forbidden with client authentication scheme &#8216;Basic&#8217;.</em></p>
<p>You still need to adjust the client application so that it passes the correct credentials to the service. Add the following lines of code to the ConsoleClient&#8217;s Main(&#8230;) method.</p>
<p><strong>Listing 16</strong> &#8211; Client Credentials</p>
<div class="csharpcode">
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre>
...
proxy.ClientCredentials.UserName.UserName = <span class="str">"Christophe"</span>;
proxy.ClientCredentials.UserName.Password = <span class="str">"WCFRocks!"</span>;
...</pre>
</div>
<p>That&#8217;s it! The client will now present valid credentials to the service and an SSL connection will be established.</p>
<p><strong>Remark</strong>: The username and password validation in this article is kept short for illustrative purposes. Replace this with you&#8217;re own validation logic in real-world applications. A better approach would be to validate the username and password against a database containing the user&#8217;s credentials.</p>
<p><a href="#top">Top of page</a></p>
<p><a title="summary" name="summary"></a><strong>Summary</strong></p>
<p>I hope you enjoyed this tutorial on how to transfer files over HTTPS using WCF. To recap what we&#8217;ve covered from a developer&#8217;s point of view:</p>
<ul>
<li>Streaming a file over WCF</li>
<li>Configuring a WCF service for communication over HTTPS(directories)</li>
<li>Generating and binding a test SSL certificate to a port</li>
<li>Consuming a service over HTTPS</li>
<li>Authenticating the server</li>
<li>Authenticating the client</li>
</ul>
<p>Any comments, questions, tips&#8230;etc. are always appreciated.</p>
<p><a href="#top">Top of page</a></p>
<p><a title="download" name="download"></a><strong>Download</strong></p>
<p>You can find the source code for this article on the <a href="http://cgeers.wordpress.com/download/" target="_blank">Download page</a> of this blog.</p>
<p><a href="#top">Top of page</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[How to add image uploading to your forms with Symfony 1.2 and Doctrine, from beginning to end]]></title>
<link>http://jonocode.wordpress.com/2009/07/31/how-to-add-image-uploading-to-your-forms-with-symfony-1-2-and-doctrine-from-beginning-to-end/</link>
<pubDate>Fri, 31 Jul 2009 16:59:24 +0000</pubDate>
<dc:creator>jjmontgo</dc:creator>
<guid>http://jonocode.wordpress.com/2009/07/31/how-to-add-image-uploading-to-your-forms-with-symfony-1-2-and-doctrine-from-beginning-to-end/</guid>
<description><![CDATA[I&#8217;m still very new to Symfony 1.2 and its form framework. Reading through documentation, discu]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I&#8217;m still very new to Symfony 1.2 and its form framework.  Reading through documentation, discussion forums and blog posts, I couldn&#8217;t find a tutorial which had everything I needed in an image upload.  Having finished an image upload for the first time, I decided to write such a tutorial.</p>
<p>This tutorial requires Symfony 1.2, the Doctrine ORM plugin and the PHP GD library.  You should already have all of these elements installed, and be familiar with them.</p>
<p>We&#8217;ll start at the beginning.  I&#8217;m going to make an uploader for a background image to attach to a Website model.  Make sure you have a field in your model to store the image file name:</p>
<pre class="brush: css;">
Website:
  columns:
    background_image:  string(255)
</pre>
<p>And rebuild your model:</p>
<pre class="brush: css;">
symfony doctrine:build-all-reload
</pre>
<p>Now open the form class generated from your schema.</p>
<p>You&#8217;re going to add a widget and a validator for the image upload.  The widget will also allow the user to view the image after it has been uploaded, and delete it if necessary.  The validator will make sure the image upload is not required (it is required by default).  There is also a second validator, sfValidatorPass, because the widget we are using adds a checkbox widget giving the user the option to delete the file.</p>
<p>You&#8217;ll also override the doSave() method and updateObject() methods.  The doSave() method will handle the upload (if there is one), create a new file name for the image, and save the image both to the file system and the background_image field automatically.  Since the background_image field is automatically set with the full path of the file, you will use updateObject() to remove the path and just store the file name.  If you move your project to another system, the file path will change and so we want to store just the file name.</p>
<p>Also in doSave(), you will handle the case where the user has checked off the &#8220;delete image&#8221; checkbox, which is automatically named background_image_delete.</p>
<p>Here is the code so far under <em>lib/form/doctrine/WebsiteForm.class.php</em>:</p>
<pre class="brush: php;">
class WebsiteForm extends BaseWebsiteForm
{
  public function configure()
  {
    $this-&gt;widgetSchema['background_image'] = new sfWidgetFormInputFileEditable(array(
      'file_src' =&gt; '/'.basename(sfConfig::get('sf_upload_dir')).'/'.$this-&gt;getObject()-&gt;getBackgroundImage(),
      'is_image' =&gt; true,
      'edit_mode' =&gt; strlen($this-&gt;getObject()-&gt;getBackgroundImage()) &gt; 0,
      'template'  =&gt; '
&lt;div&gt;%file%
%input%
%delete% %delete_label%&lt;/div&gt;
'
    ));

    $this-&gt;validatorSchema['background_image'] = new sfValidatorFile(array(
      'required' =&gt; false,
      'mime_types' =&gt; 'web_images'
    ));
    $this-&gt;validatorSchema['background_image_delete'] = new sfValidatorPass();
  }

  protected function doSave ( $con = null )
  {
    $upload = $this-&gt;getValue('background_image');

    if ( $upload )
    {
      $filename = sha1($upload-&gt;getOriginalName().microtime().rand()).$upload-&gt;getExtension($upload-&gt;getOriginalExtension());
      $filepath = sfConfig::get('sf_upload_dir').'/'.$filename;

      $oldfilepath = sfConfig::get('sf_upload_dir').'/'.$this-&gt;getObject()-&gt;getBackgroundImage();
      if ( file_exists($oldfilepath) )
      {
        unlink($oldfilepath);
      }

      $upload-&gt;save($filepath);
    }

    $delete = $this-&gt;getValue('background_image_delete');
    if ( $delete )
    {
      $filename = $this-&gt;getObject()-&gt;getBackgroundImage();
      $filepath = sfConfig::get('sf_upload_dir').'/'.$filename;
      @unlink($filepath);
      $this-&gt;getObject()-&gt;setBackgroundImage(null);
    }

    return parent::doSave($con);
  }

  public function updateObject($values = null)
  {
    $object = parent::updateObject($values);
    $object-&gt;setBackgroundImage(str_replace(sfConfig::get('sf_upload_dir').'/', '', $object-&gt;getBackgroundImage()));
    return $object;
  }

}
</pre>
<p>This should work well for the most part.  But what if the image is 2000 pixels in width?  It will be very disruptive to display such a large image.</p>
<p>That&#8217;s where <a href="http://www.symfony-project.org/plugins/sfThumbnailPlugin">sfThumbnailPlugin</a> comes in.</p>
<p>Install the plugin if you haven&#8217;t already done so:</p>
<pre class="brush: bash;">
$ symfony plugin:install sfThumbnailPlugin
$ php symfony cc
</pre>
<p>Now create a new directory to store your thumbnails:</p>
<pre class="brush: bash;">
$ mkdir /web/uploads/thumbnails
</pre>
<p>You&#8217;ll probably want to use this directory in other modules or applications in your project.  Add a new setting called sf_thumbnail_dir in your project configuration:</p>
<p><em>config/ProjectConfiguration.class.php</em></p>
<pre class="brush: php;">
...
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    ...
    sfConfig::set('sf_thumbnail_dir', sfConfig::get('sf_upload_dir').'/thumbnails');
    ...
  }
}
</pre>
<p>Now all that&#8217;s left to do is create and store the thumbnail from the doSave() method of your form class, and make sure that your form displays the thumbnail and not the source image in your configure() method.</p>
<p>Modify the widget settings so that it displays the thumbnail.  Note that I&#8217;ve &#8230;&#8217;d most of the parts that don&#8217;t change:</p>
<p><em>lib/form/doctrine/WebsiteForm.class.php</em></p>
<pre class="brush: php;">
class WebsiteForm extends BaseWebsiteForm
{
  public function configure()
  {
    ...
    $this-&gt;widgetSchema['background_image'] = new sfWidgetFormInputFileEditable(array(
      'file_src' =&gt; '/'.basename(sfConfig::get('sf_upload_dir')).'/'.basename(sfConfig::get('sf_thumbnail_dir')).'/'.$this-&gt;getObject()-&gt;getBackgroundImage(),
      'is_image' =&gt; true,
      'edit_mode' =&gt; strlen($this-&gt;getObject()-&gt;getBackgroundImage()) &gt; 0,
      'template'  =&gt; '
&lt;div&gt;%file%
%input%
%delete% %delete_label%&lt;/div&gt;
'
    ));
    ...
  }

  protected function doSave ( $con = null )
  {
    $upload = $this-&gt;getValue('background_image');

    if ( $upload )
    {
      ...
      $thumbnailpath = sfConfig::get('sf_thumbnail_dir').'/'.$filename;
      ...
      $oldthumbnailpath = sfConfig::get('sf_thumbnail_dir').'/'.$this-&gt;getObject()-&gt;getBackgroundImage();
      if ( file_exists($oldthumbnailpath) )
      {
        unlink($oldthumbnailpath);
      }

      ...
      $thumbnail = new sfThumbnail(150, 150, true, true, 75, 'sfGDAdapter');
      $thumbnail-&gt;loadFile($filepath);
      $thumbnail-&gt;save($thumbnailpath);
    }

    $delete = $this-&gt;getValue('background_image_delete');

    if ( $delete )
    {
      ...
      $thumbnailpath = sfConfig::get('sf_thumbnail_dir').'/'.$filename;
      @unlink($thumbnailpath);
      ...
    }
  }

  ...

}
</pre>
<p>And that&#8217;s all there is to it.  Note that there is no template file here because the form framework handles the view of the form inputs.</p>
<p>Questions?  Complaints?  Leave a comment.</p>
<p><a href="http://api.tweetmeme.com/share?url=http://jonocode.wordpress.com/2009/07/31/how-to-add-image-uploading-to-your-forms-with-symfony-1-2-and-doctrine-from-beginning-to-end/"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http://jonocode.wordpress.com/2009/07/31/how-to-add-image-uploading-to-your-forms-with-symfony-1-2-and-doctrine-from-beginning-to-end/" height="61" width="51" /></a> </p>
<p>Here are some related resources:</p>
<ul>
<li><a href="http://www.symfony-project.org/forms/1_2/en/A-Widgets#chapter_a_sub_sfwidgetforminputfileeditable">sfWidgetFormInputFileEditable documentation</a></li>
<li><a href="http://www.symfony-project.org/forms/1_2/en/B-Validators#chapter_b_sub_sfvalidatorfile">sfValidatorFile documentation</a></li>
<li><a href="http://www.symfony-project.org/plugins/sfThumbnailPlugin/1_5_6?tab=plugin_readme">sfThumbnailPlugin readme</a></li>
</ul>
<p>Here are some other posts you might be interested in:</p>
<ul>
<li><a href="http://jonocode.wordpress.com/2009/07/11/adding-sf_guard_user_profile-to-the-sfdoctrineguardplugin/">Adding to the sfDoctrineGuardPlugin</a></li>
<li><a href="http://jonocode.wordpress.com/2009/06/22/how-to-secure-fckeditor-against-unauthorized-access-in-a-symfony-application/">How to secure FCKEditor against unauthorized access in a Symfony application</a></li>
<li><a href="http://jonocode.wordpress.com/2009/07/22/table-level-behaviors-will-remove-global-behaviors-in-doctrine-schemas/">Table-level behaviors will remove global behaviors in Doctrine schemas</a></li>
</ul>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Kewlshare- Host your files and earn money]]></title>
<link>http://earnmoneykewlshare.wordpress.com/2009/07/29/kewlshare-host-your-files-and-earn-money/</link>
<pubDate>Wed, 29 Jul 2009 12:47:07 +0000</pubDate>
<dc:creator>yasmin958</dc:creator>
<guid>http://earnmoneykewlshare.wordpress.com/2009/07/29/kewlshare-host-your-files-and-earn-money/</guid>
<description><![CDATA[Kewlshare.com  is a provider of images, audio,video, docs, pdf, zip or any other type files &#8230; ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Kewlshare.com  is a provider of images, audio,video, docs, pdf, zip or any other type files &#8230;<br />
You can upload any document without restrictions.</p>
<p><a href="http://kewlshare.com/register.php?refer=0f3827d3"><img class="aligncenter size-full wp-image-6" title="kewlshareb1" src="http://earnmoneykewlshare.wordpress.com/files/2009/07/kewlshareb11.gif" alt="kewlshareb1" width="480" height="60" /></a></p>
<p>Apart from download, you can watch or listen online  any file you upload to your account. A unique link will be provide to every uploaded file, which can be shared via e-mail, Website, Blog, forums, My Space, Face book etc with your friends for free download.</p>
<p>You can upload photos, audio, video, documents or anything else are maximum file size is 500 MB. You will get money when some one downloads your file from kewlshare links.</p>
<p>Your paments send via PayPal.You will get the payment with in 12 to 20 business</p>
<p><span style="color:#ff00ff;"><strong><a href="http://kewlshare.com/register.php?refer=0f3827d3">Click here to Register Kewlshare&#8230;</a></strong></span></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[On-demand Drag n Drop zones]]></title>
<link>http://centraldesktophero.wordpress.com/2009/06/25/on-demand-drag-n-drop-zones/</link>
<pubDate>Thu, 25 Jun 2009 21:29:43 +0000</pubDate>
<dc:creator>albush</dc:creator>
<guid>http://centraldesktophero.wordpress.com/2009/06/25/on-demand-drag-n-drop-zones/</guid>
<description><![CDATA[I love Central Desktop&#8217;s &#8220;Drag n Drop&#8221; upload capability. It is probably the one f]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I love Central Desktop&#8217;s &#8220;Drag n Drop&#8221; upload capability. It is probably the one feature I use more than any other on a consistent basis. If I need to upload a batch of files to a folder, it never fails me. But the Drag n Drop is only good for uploading files in bulk, right? Not neceissarily, if you know how to tweak a URL or two, you can upload files quickly and easily to any folder you specify and even tag them at the same time.<!--more--></p>
<p>I have two methods, today, for getting more out of CD&#8217;s Drag n Drop upload tool. Both are designed to be used in repeatable circumstances, and thus aren&#8217;t appropriate for one-off tasks. (A little disclaimer here, I work almost exclusively in Firefox on a Windows XP box.  I have a MacBook for personal use, and most of the techniques I describe on this site work on both. Your mileage may vary from OS to OS.)</p>
<p>First up, the sidebar upload box. One great thing about the DND zone is that you don&#8217;t need the popup window to upload. You can embed the zone in a wiki page, open it up in a new tab in your browser, or summon it as a bookmark in Firefox&#8217;s sidebar. But to get there, we need to learn a little bit more about the DND zone and how it works.</p>
<p>(A little disclaimer here, I work almost exclusively in Firefox on a Windows XP box.  I have a MacBook for personal use, and most of the techniques I describe on this site work on both. Your mileage may vary from OS to OS.)</p>
<p>Each DND zone has its own URL. Here&#8217;s a sample: https://YOURDOMAIN.centraldesktop.com/spaces/javaupload?upload_type=std&#38;spid=93938&#38;spacename=AlanSandbox&#38;cat=719544&#38;dbid=&#38;catname=Jones%20Account&#38;tag=  To get this URL I just summoned a DND zone from the workspace and folder I wanted to upload to, then double clicked on the padlock icon at the bottom of the new window. Then, by navigating to the &#8220;General&#8221; tab, I can see my URL.</p>
<div id="attachment_43" class="wp-caption alignleft" style="width: 489px"><img class="size-full wp-image-43" title="dndzones_findurl" src="http://centraldesktophero.wordpress.com/files/2009/06/dndzones_findurl.png" alt="Where to find DND zone URL" width="479" height="272" /><p class="wp-caption-text">Where to find DND zone URL</p></div>
<p>Now let&#8217;s parse this URL.</p>
<p>https://YOURDOMAIN.centraldesktop.com/spaces/javaupload?upload_type=std  This starts off the URL, nothing to tweak here.</p>
<p>&#38;spid=93938&#38;spacename=AlanSandbox  Here&#8217;s your workspace id (spid) and workspace name. The workspace name parameter only affects the workspace name as displayed in the DND zone</p>
<p>&#38;dbid=  Database ID. (We&#8217;ll look at this later)</p>
<p>&#38;catname=Jones%20Account  Folder name (be sure to use the &#8220;%20&#8243; in lieu of spaces.)</p>
<p>&#38;tag=  Yes, you can use the DND zone to upload with tags. (I love this part.)</p>
<p>So now what do we do with all of this? Here&#8217;s how I use it. Every week I have several reports to upload for each account. And each report has to be tagged with a certain tag. Now I can go to the Jones Account folder, hit the &#8220;Single File Upload&#8221; link, navigate to the file I need, select it, choose my tags (double check that I have the right tag) and then upload it. Or, I can use a custom URL to create a bookmark that loads in the sidebar. I don&#8217;t even have to be in the Jones Account folder to upload the file.</p>
<p>So I just add in the appropriate tags and get &#8220;https://YOURDOMAIN.centraldesktop.com/spaces/javaupload?upload_type=std&#38;spid=93938&#38;spacename=AlanSandbox&#38;cat=719544&#38;dbid=&#38;catname=Jones%20Account&#38;tag=TPSReports&#8221; Paste that URL into a new bookmark, and set it to open in the sidebar.</p>
<div id="attachment_44" class="wp-caption alignleft" style="width: 368px"><img class="size-full wp-image-44" title="upload" src="http://centraldesktophero.wordpress.com/files/2009/06/upload.png" alt="The finished product" width="358" height="297" /><p class="wp-caption-text">The finished product</p></div>
<p>The second technique is for database records. I&#8217;m always uploading files to database records, and the easiest way to for me to upload files is via the DND zone. So to save a few minutes each time, I had a new file to upload to a database.</p>
<p>I employed the technique above, and combined it with a previous tip on creating <a href="http://centraldesktophero.wordpress.com/2009/06/01/firefox-quick-searches/">Firefox Quick Search</a> Shortcuts, and have put them together to save a ton of time.</p>
<p>First, I navigated to a database record in the database I want to use. Any record will do, we&#8217;re more interested in things like database id and workspace id right now.</p>
<p>https://YOURDOMAIN.centraldesktop.com/spaces/javaupload?upload_type=db&#38;spid=93938&#38;spacename=AlanSandbox&#38;cat=-4&#38;dbid=93938_9686884qkol8s98ap0kzg96kvs9ifbpg&#124;2&#124;9686884qkol8s98ap0kzg96kvs9ifbpg&#38;catname=Attachments&#38;tag=</p>
<p>Again, we&#8217;ll add any tags we want, and, if we want, populate the catname parameter with a folder name.</p>
<p>The number between the pipes (&#124;) is the record ID. We want this to be our input parameter, so we use Firefox&#8217;s search shortcut %s in place of the record ID, and we end up with a URL that looks like: https://YOURDOMAIN.centraldesktop.com/spaces/javaupload?upload_type=db&#38;spid=93938&#38;spacename=AlanSandbox&#38;cat=-4&#38;dbid=93938_9686884qkol8s98ap0kzg96kvs9ifbpg&#124;<span style="color:#ff0000;">%s</span>&#124;9686884qkol8s98ap0kzg96kvs9ifbpg&#38;catname=Attachments&#38;tag=<span style="color:#ff0000;">tpscoversheet</span></p>
<p><span style="color:#ff0000;"><span style="color:#000000;">Now we just use that newly created URL to create a Quick Search with a keyword of your choice, like &#8220;tpscvr&#8221; </span></span></p>
<p><span style="color:#ff0000;"><span style="color:#000000;">To use this trick, just type in tpscvr &#60;record id&#62; into the address bar, and a DND zone will open up for you.<br />
</span></span></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Protect file uploads via PHP]]></title>
<link>http://svnlabs.wordpress.com/2009/06/12/protect-file-uploads-via-php/</link>
<pubDate>Fri, 12 Jun 2009 11:53:15 +0000</pubDate>
<dc:creator>svnlabs</dc:creator>
<guid>http://svnlabs.wordpress.com/2009/06/12/protect-file-uploads-via-php/</guid>
<description><![CDATA[Check server-side MIME type of uploaded files The PHP form variable $_FILES['file']['type'] does not]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><strong>Check </strong><strong>server-side</strong><strong> MIME type of uploaded files<br />
</strong></p>
<p>The PHP form variable $_FILES['file']['type'] does not return correct mime type, so we have to use some php functions like&#8230;&#8230;.<br />
&#62; finfo_file()<br />
&#62; getimagesize()<br />
&#62; exif_imagetype()</p>
<pre class="brush: php;">

if(version_compare(substr(PHP_VERSION,0,1),5) == -1)
{
$san	= finfo_open(FILEINFO_MIME);
$mime	= finfo_file($san,$FileName);
$tmpvar = explode(&amp;#34;;&amp;#34;, $mime);
finfo_close($san);
if($mime == &amp;#34;image/jpeg&amp;#34;)
{
echo &amp;#34;this is jpeg&amp;#34;;
}
else
{
echo &amp;#34;this is not jpeg&amp;#34;;
}
}
</pre>
<p>One can use getID3 [http://getid3.sourceforge.net/] classes to get mime type other than images&#8230;.</p>
<p><strong>Don&#8217;t upload to a web accessible directory</strong></p>
<p>Protect your directory to execute perticular file type by putting a .htacces file in directory<strong></strong></p>
<p><strong></strong><code>AddType text/plain .php .js .cgi</code></p>
<p>more help here:</p>
<p>http://www.askapache.com/htaccess/mod_rewrite-tips-and-tricks.html</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Protect file uploads via PHP]]></title>
<link>http://sandeepkonstant.wordpress.com/2009/06/12/protect-file-uploads-via-php/</link>
<pubDate>Fri, 12 Jun 2009 11:53:15 +0000</pubDate>
<dc:creator>sandeepkonstant</dc:creator>
<guid>http://sandeepkonstant.wordpress.com/2009/06/12/protect-file-uploads-via-php/</guid>
<description><![CDATA[Check server-side MIME type of uploaded files The PHP form variable $_FILES['file']['type'] does not]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><strong>Check </strong><strong>server-side</strong><strong> MIME type of uploaded files<br />
</strong></p>
<p>The PHP form variable $_FILES['file']['type'] does not return correct mime type, so we have to use some php functions like&#8230;&#8230;.<br />
&#62; finfo_file()<br />
&#62; getimagesize()<br />
&#62; exif_imagetype()</p>
<pre class="brush: php;">

if(version_compare(substr(PHP_VERSION,0,1),5) == -1)
{
$san	= finfo_open(FILEINFO_MIME);
$mime	= finfo_file($san,$FileName);
$tmpvar = explode(&quot;;&quot;, $mime);
finfo_close($san);
if($mime == &quot;image/jpeg&quot;)
{
echo &quot;this is jpeg&quot;;
}
else
{
echo &quot;this is not jpeg&quot;;
}
}
</pre>
<p>One can use getID3 [http://getid3.sourceforge.net/] classes to get mime type other than images&#8230;.</p>
<p><strong>Don&#8217;t upload to a web accessible directory</strong></p>
<p>Protect your directory to execute perticular file type by putting a .htacces file in directory<strong></strong></p>
<p><strong></strong><code>AddType text/plain .php .js .cgi</code></p>
<p>more help here:</p>
<p>http://www.askapache.com/htaccess/mod_rewrite-tips-and-tricks.html</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[File Upload using JSP]]></title>
<link>http://sudanlive.wordpress.com/2009/06/01/file-upload-using-jsp/</link>
<pubDate>Mon, 01 Jun 2009 08:07:54 +0000</pubDate>
<dc:creator>sudan</dc:creator>
<guid>http://sudanlive.wordpress.com/2009/06/01/file-upload-using-jsp/</guid>
<description><![CDATA[Today i am going to explain about a interesting problem, that i faced during the course of my projec]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Today i am going to explain about a interesting problem, that i faced during the course of my project development.</p>
<p>I was trying to do a file upload using jsp from a client to  server. For this when i searched the net, i got many code, at last i managed to edit one such code and customized it to my requirement. Here is the below code snippet of the form, which is used to upload a file.</p>
<p>File Name:<strong> <span style="color:#ff9900;">FileUploadForm.jsp</span></strong></p>
<p>&#60;FORM ENCTYPE=&#8221;multipart/form-data&#8221; METHOD=&#8221;post&#8221; name=&#8221;main&#8221; action=&#8221;FileUploadAction.jsp&#8221;&#62;<br />
&#60;br&#62;<br />
&#60;tr&#62;<br />
&#60;td align=&#8221;right&#8221;&#62;&#60;b&#62;Choose the file To Upload:&#60;/b&#62;&#60;/td&#62;<br />
&#60;td&#62;&#60;INPUT NAME=&#8221;F1&#8243; TYPE=&#8221;file&#8221;&#62;&#60;/td&#62;<br />
&#60;/tr&#62;<br />
&#60;tr&#62;<br />
&#60;td&#62;&#38;nbsp;&#60;/td&#62;<br />
&#60;td&#62;<br />
&#60;INPUT TYPE=&#8221;button&#8221; VALUE=&#8221;Upload&#8221; onclick=uploadFile()&#62;<br />
&#60;/td&#62;<br />
&#60;/tr&#62;<br />
&#60;/FORM&#62;</p>
<p>Below scriplet is the code of other file which does the file upload action to the server</p>
<p>File Name: <span style="color:#ff9900;"><strong>FileUploadAction.jsp</strong></span><br />
&#60;%<br />
//to get the content type information from JSP Request Header<br />
String contentType = request.getContentType();<br />
//here we are checking the content type is not equal to Null and as well as the passed data from mulitpart/form-data is greater than or equal to 0<br />
if ((contentType != null) &#38;&#38; (contentType.indexOf(&#8220;multipart/form-data&#8221;) &#62;= 0)) {<br />
DataInputStream in = new DataInputStream(request.getInputStream());<br />
//we are taking the length of Content type data<br />
int formDataLength = request.getContentLength();<br />
byte dataBytes[] = new byte[formDataLength];<br />
int byteRead = 0;<br />
int totalBytesRead = 0;<br />
//this loop converting the uploaded file into byte code<br />
while (totalBytesRead &#60; formDataLength) {<br />
byteRead = in.read(dataBytes, totalBytesRead, formDataLength);<br />
totalBytesRead += byteRead;<br />
}<span style="color:#ff9900;"><br />
</span> <span style="color:#3366ff;"><strong><span style="color:#ff9900;">S</span><span style="color:#ff9900;">tring file = new String(dataBytes);</span></strong></span><br />
//for saving the file name<br />
String saveFile = file.substring(file.indexOf(&#8220;filename=\&#8221;") + 10);<br />
saveFile = saveFile.substring(0, saveFile.indexOf(&#8220;\n&#8221;));<br />
saveFile = saveFile.substring(saveFile.lastIndexOf(&#8220;\\&#8221;) + 1,saveFile.indexOf(&#8220;\&#8221;"));</p>
<p>String timestamp = new SimpleDateFormat(&#8220;yyyy.MM.dd.HH.mm.ss.S.&#8221;).format(new Date());<br />
saveFile = userId+timestamp+saveFile;<br />
int lastIndex = contentType.lastIndexOf(&#8220;=&#8221;);<br />
String boundary = contentType.substring(lastIndex + 1,contentType.length());<br />
int pos;<br />
//extracting the index of file<br />
pos = file.indexOf(&#8220;filename=\&#8221;");<br />
pos = file.indexOf(&#8220;\n&#8221;, pos) + 1;<br />
pos = file.indexOf(&#8220;\n&#8221;, pos) + 1;<br />
pos = file.indexOf(&#8220;\n&#8221;, pos) + 1;</p>
<p>int boundaryLocation = file.indexOf(boundary, pos) &#8211; 4;<br />
int startPos = ((file.substring(0, pos)).getBytes()).length;<br />
int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length;</p>
<p>// creating a new file with the same name and writing the content in new file<br />
String fileName = request.getRealPath(&#8220;&#8221;)+&#8221;\\excelFiles\\&#8221;+saveFile;<br />
FileOutputStream fileOut = new FileOutputStream(fileName);<br />
fileOut.write(dataBytes, startPos, (endPos &#8211; startPos));<br />
fileOut.flush();<br />
fileOut.close();</p>
<p>%&#62;</p>
<p>But there is a serious problem in the above code, it works fine in the windows, whereas in linux machines this code fails. When i went through the everyline of the code, the line of code which gives different output in linux is,</p>
<p><span style="color:#3366ff;"><strong><span style="color:#ff9900;">S</span><span style="color:#ff9900;">tring file = new String(dataBytes);</span></strong></span><br />
The above line is used to convert the file data in bytes to String. The reason we are doing is to find the boundary location of the file, now lets dont go deep in to this, this is more about file parsing formats. You can read the <a title="Form-based File Upload in HTML" href="http://www.ietf.org/rfc/rfc1867.txt" target="_blank">RFC </a>which explains about the formats and parsing the file data from a HTML. But the strange that i could see in the above line is for the same file uploaded the String variable file length varies in windows server and linux server. I am not able to imaging the reason behind this.</p>
<p>After a long fight with the code and searching in the internet, i happen to see the apache commons api&#8217;s. This api is really cool and interesting. It does all the things that is required for parsing and reduces our load. FileUploadForm.jsp can be used the same. But i changes the code of FileUploadAction.jsp. Below is the code</p>
<p>File Name: <span style="color:#ff9900;"><strong>FileUploadAction.jsp </strong></span></p>
<p>&#60;%@ page import=&#8221;java.text.SimpleDateFormat&#8221; %&#62;<br />
&#60;%@ page import=&#8221;org.apache.commons.fileupload.FileItem&#8221; %&#62;<br />
&#60;%@ page import=&#8221;org.apache.commons.fileupload.FileUploadException&#8221; %&#62;<br />
&#60;%@ page import=&#8221;org.apache.commons.fileupload.disk.DiskFileItemFactory&#8221; %&#62;<br />
&#60;%@ page import=&#8221;org.apache.commons.fileupload.servlet.ServletFileUpload&#8221; %&#62;</p>
<p>&#60;%@ page import=&#8221;java.io.*&#8221; %&#62;<br />
&#60;%@ page import=&#8221;java.util.*&#8221; %&#62;<br />
&#60;%</p>
<p>if (ServletFileUpload.isMultipartContent(request)){<br />
ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());<br />
List fileItemsList = null;<br />
try {<br />
fileItemsList = servletFileUpload.parseRequest(request);<br />
} catch (FileUploadException e) {<br />
System.err.println(&#8220;inside uploadUpdateACtion while parsing Exception is ["+e.getMessage()+"]&#8220;);<br />
}</p>
<p>Iterator i = fileItemsList.iterator();<br />
//String comment = ((FileItem)i.next()).getString();<br />
FileItem fi = (FileItem)i.next();<br />
// filename on the client<br />
String fileName = fi.getName();</p>
<p>fileName = fileName.substring(fileName.lastIndexOf(&#8220;\\&#8221;)+1);</p>
<p>String timestamp = new SimpleDateFormat(&#8220;yyyy.MM.dd.HH.mm.ss.S.&#8221;).format(new Date());<br />
String saveFile = userId+timestamp+fileName;<br />
// write the file<br />
try {<br />
fi.write(new File(request.getRealPath(&#8220;&#8221;)+&#8221;/excelFiles&#8221;, saveFile));<br />
} catch (Exception e) {<br />
System.err.println(&#8220;inside uploadUpdateACtion while writing the uploded file Exception is ["+e.getMessage()+"]&#8220;);<br />
}</p>
<p>%&#62;</p>
<p>For the above code to work we need two jars to be included in the classpath <span style="color:#ff9900;">commons-fileupload-1.2.1.jar</span> and <span style="color:#ff9900;">commons-io-1.4.jar. <span style="color:#000000;">Both the jars are available in the apache site. This code will work for all environments and platforms. It has lot of features to be explored by me.</span></span><br />
Thanks for reading, Have a great day !!!!!!!!!!!!!!!!!!!!!!!!!!!</p>
<p>-Sudan</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[SharePoint Document Library and List – File Upload]]></title>
<link>http://kartooz.wordpress.com/2009/05/27/sharepoint-document-library-and-list-file-upload/</link>
<pubDate>Wed, 27 May 2009 14:54:04 +0000</pubDate>
<dc:creator>Karthikeyan Kasiviswanathan</dc:creator>
<guid>http://kartooz.wordpress.com/2009/05/27/sharepoint-document-library-and-list-file-upload/</guid>
<description><![CDATA[There are different ways you can add documents to a doc library or to list item as an attachment. Yo]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>There are different ways you can add documents to a doc library or to list item as an attachment. You could use object model, built-in web service, custom web service that uses object model, or HTTP PUT method.</p>
<p>In this post I will be stepping through them in detail. Let us take the object model approach first. For the sake of simplicity I have created a simple windows forms app that will push documents in to the document library and list</p>
<p>&#160;</p>
<p><strong><u>Adding documents to a Document Library and updating document attributes :</u></strong></p>
<div id="codeSnippetWrapper" style="border-right:silver 1px solid;border-top:silver 1px solid;font-size:8pt;overflow:auto;border-left:silver 1px solid;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;border-bottom:silver 1px solid;font-family:&#39;background-color:#f4f4f4;text-align:left;margin:20px 0 10px;padding:4px;">
<div id="codeSnippet" style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;padding:0;">
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">void</span> button1_Click(<span style="color:#0000ff;">object</span> sender, EventArgs e)</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   2:</span>         {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   3:</span>             <span style="color:#0000ff;">if</span> (openFileDialog1.ShowDialog() == DialogResult.OK)</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   4:</span>             {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   5:</span>                 <span style="color:#0000ff;">try</span></pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   6:</span>                 {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   7:</span>                     FileStream myStream;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   8:</span>                     <span style="color:#0000ff;">string</span> fullName;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   9:</span>                     <span style="color:#0000ff;">if</span> ((myStream = (FileStream)openFileDialog1.OpenFile()) != <span style="color:#0000ff;">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  10:</span>                     {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  11:</span>                         fullName = openFileDialog1.FileName;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  12:</span>                         FileInfo myFileInfo = <span style="color:#0000ff;">new</span> FileInfo(fullName);</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  13:</span>                         <span style="color:#0000ff;">using</span> (myStream)</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  14:</span>                         {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  15:</span>                             <span style="color:#0000ff;">using</span> (SPSite oSite = <span style="color:#0000ff;">new</span> SPSite(<span style="color:#006080;">&#34;http://vslearnmoss/sites/FileUpload&#34;</span>))</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  16:</span>                             {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  17:</span>                                 <span style="color:#0000ff;">using</span> (SPWeb oWeb = oSite.OpenWeb())</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  18:</span>                                 {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  19:</span>                                     SPFolderCollection oFolders = oWeb.GetFolder(<span style="color:#006080;">&#34;MyDocuments&#34;</span>).SubFolders;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  20:</span>                                     SPFolder oFolder = oFolders[<span style="color:#006080;">&#34;Folder1&#34;</span>];</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  21:</span>                                     SPFileCollection oFileColl = oFolder.Files;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  22:</span>                                     Hashtable oDocAttribs = <span style="color:#0000ff;">new</span> Hashtable { { <span style="color:#006080;">&#34;Field1&#34;</span>, <span style="color:#006080;">&#34;Value1&#34;</span> }, { <span style="color:#006080;">&#34;Field2&#34;</span>, <span style="color:#006080;">&#34;Value2&#34;</span> } };</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  23:</span>                                     SPFile oFile = oFileColl.Add(myFileInfo.Name, myStream, oDocAttribs, <span style="color:#0000ff;">true</span>);</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  24:</span>                                 }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  25:</span>                             }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  26:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  27:</span>                         }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  28:</span>                     }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  29:</span>                 }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  30:</span>                 <span style="color:#0000ff;">catch</span> (Exception ex)</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  31:</span>                 {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  32:</span>                     MessageBox.Show(<span style="color:#006080;">&#34;Error: &#34;</span> + ex.Message);</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  33:</span>                 }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  34:</span>             }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  35:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  36:</span>         }</pre>
<p><!--CRLF--></div>
</div>
<p><strong><u>Adding document attachments to a list item&#160; :</u></strong></p>
<div id="codeSnippetWrapper" style="border-right:silver 1px solid;border-top:silver 1px solid;font-size:8pt;overflow:auto;border-left:silver 1px solid;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;border-bottom:silver 1px solid;font-family:&#39;background-color:#f4f4f4;text-align:left;margin:20px 0 10px;padding:4px;">
<div id="codeSnippet" style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;padding:0;">
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">void</span> button1_Click(<span style="color:#0000ff;">object</span> sender, EventArgs e)</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   2:</span>         {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   3:</span>             <span style="color:#0000ff;">if</span> (openFileDialog1.ShowDialog() == DialogResult.OK)</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   4:</span>             {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   5:</span>                 <span style="color:#0000ff;">try</span></pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   6:</span>                 {                    </pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   7:</span>                     <span style="color:#0000ff;">string</span> fullName;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   8:</span>                     fullName = openFileDialog1.FileName;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   9:</span>                     FileInfo myFileInfo = <span style="color:#0000ff;">new</span> FileInfo(fullName);</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  10:</span>                     <span style="color:#0000ff;">byte</span>[] fileData = System.IO.File.ReadAllBytes(fullName);</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  11:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  12:</span>                     <span style="color:#0000ff;">using</span> (SPSite oSite = <span style="color:#0000ff;">new</span> SPSite(<span style="color:#006080;">&#34;http://vslearnmoss/sites/FileUpload&#34;</span>))</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  13:</span>                     {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  14:</span>                         <span style="color:#0000ff;">using</span> (SPWeb oWeb = oSite.OpenWeb())</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  15:</span>                         {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  16:</span>                             SPList oList = oWeb.Lists[<span style="color:#006080;">&#34;MyList&#34;</span>];</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  17:</span>                             SPQuery oQuery = <span style="color:#0000ff;">new</span> SPQuery { Query = <span style="color:#006080;">&#34;0&#34;</span> };</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  18:</span>                             SPListItem oItem = oList.GetItems(oQuery).Add();</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  19:</span>                             oItem[<span style="color:#006080;">&#34;Title&#34;</span>] = textBox1.Text;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  20:</span>                             SPAttachmentCollection attachments = oItem.Attachments;</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  21:</span>                             attachments.Add(myFileInfo.Name, fileData);</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  22:</span>                             oItem.Update();</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  23:</span>                         }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  24:</span>                     }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  25:</span>                 }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  26:</span>                 <span style="color:#0000ff;">catch</span> (Exception ex)</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  27:</span>                 {</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  28:</span>                     MessageBox.Show(<span style="color:#006080;">&#34;Error: &#34;</span> + ex.Message);</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  29:</span>                 }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  30:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:white;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  31:</span>             }</pre>
<p><!--CRLF--></p>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&#39;background-color:#f4f4f4;text-align:left;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  32:</span>         }</pre>
<p><!--CRLF--></div>
</div>
<p>One thing to note when accessing the list for creating a new list item is to be mindful that when SPList.Items.Add is called it fetches all the items before creating a new item, one way to avoid is to make a blank query that fetches zero results and add a new list item to the collection. [Thanks to Rob Garret]</p>
<p>SPQuery oQuery = new SPQuery { Query = &#34;0&#34; }; </p>
<p>SPListItem oItem = oList.GetItems(oQuery).Add();</p>
<p>&#160;</p>
<p>You can look for more info about adding list item efficiently in this <a href="http://blog.robgarrett.com/2009/02/25/efficient-way-to-add-a-new-item-to-a-sharepoint-list/" target="_blank">article</a> by Rob Garret.</p>
<p>In the next part of this article, I will show you how to utilize web services or HTTP PUT method to push documents into the SharePoint document library.</p>
</div>]]></content:encoded>
</item>

</channel>
</rss>
