Update
The API I wrote about in this article has been removed from recent versions ofFirefox. Instead, you can now use a FileReader
object to read files onthe client, and a FormData
object to serialize such file values and POSTthem using asynchronous requests. These two objects are also available in Chromeand Safari, possible other browsers too. However, I'll keep the old article herefor posterity. Here goes.
- Octet streams are quite simply larger sequences made up of 8 bit integers (AKA smaller 8 binary digit sequences). As you may have guessed, everything is an octet stream, just a stream of these 8.
- Using - AlamofireImage (3.0.0): @cnoon trying load image to UIImageView from url request which gives binary stream. But fails with this error Swift._DebuggerSupport.
The file is downloaded but badly in a wrong encoding! When i dowload the data in the servlet to a file its different to the file saved via your script.
Old Article
I don't know about you, but there's one little thing I've always hated about Ajax.The impossibility of file uploading. I still remember the ugly day when Idiscovered the terrible truth. There was no chance on earth you could send a fileusing an XMLHttpRequest
, thus workarounds appeared. Google made use of a hiddeniframe to imitate such an asynchronous call for their Gmail service, and later on,Flash based uploaders appeared. Things are though going forward.
Firefox 3 introduced a new API,that few people know about, which allows JavaScript to read local files selectedby an user from a form file-upload dialog. A copy of Firefox 3 with default settingsoffers full access to this new programming interface. So we'll embrace the challengeand write a little JavaScript uploader on top of this newAPI.
However, if you're not into reading this long article, just go ahead and look atthe complete source code in my GitHub repo.
Goal
In this tutorial we'll write a little application that is able to read and uploadlocal files to a remote web server using an asynchronousHTTP request. The whole applicationconsists of three parts:
- the client side comprised of JavaScript, HTMLand a little CSS
- the server side script, written in PHP
- the communication channel in between them, old good HTTP
We'll start with the JavaScript side, as I'm sure you're eager to find about thenew file access API, thenwe'll review the XMLHttpRequest
object as available in Firefox version 3 (it gotenhanced with a new method). After the client-side part follows explanations forthe server-side script, written in PHP, continued with a little summary over theHTTP protocol concerning datatransmission and HTML forms.Finally, we'll put all these together to build a powerful asynchronous fileuploader.
The Firefox file upload API
When Firefox 3 has been launched in June this year, we heard a lot about theimprovements it brought to the web development field by further implementingexisting standards and technologies like HTML,CSS and JavaScript. One thing Ihave never seen mentioned was the interface for reading local files, providedthe file is chosen by the user through an HTMLfile input element. For example, a simple Google search for getAsBinary, one ofthe new methods in the API,will give you few results, even when counting the false positives (such a falsepositive is related to ColdFusion which has a similar method name, and resultscomprising information about it are preponderant). That surprises me a lot as,in my opinion, it is a huge step forward in building more powerful web applications.Actually, there is someone that wrote about it in May 2008. Alas the newshasn't spread. With this new API,each input element (not only file input elements), is given a property called files.This property is our gateway to reading local files. When the type attribute ofthe input element isn't file, the value of the files property is null. On theother hand, for input elements whose type attribute is file, the files propertyis of type FileList
and resembles a NodeList
object returned by, let's say,document.getElementsByTagName()
. You may access it as if it were an Array
and has the following properties and methods:
length
item(index)
Each element in the files property is a File element that exposes the followingproperties and methods:
fileName
fileSize
getAsBinary()
getAsText(encoding)
getAsDataURL()
Those two lists above are all there is to know about theAPI for reading localfiles. There is nothing more about it. No security restrictions, no specialconfigurations. As I'm sure the files property itself poses no problem inunderstanding its interface let's review the contained file objects with a littlescript. You may want to download Firebug in order to get a thoroughunderstanding of the following exploration. Here's the code that we'll use:
The fileName
property gives us the name of the picked up file, but not theabsolute path on the filesystem, just the basename. Modify the above source codeabove so that the JavaScript part now becomes:
The getAsBinary()
method will read the contents of the file and return them inbinary representation. If you select a binary file, an image for example, youshould see some weird characters, question marks or even rectangles in the alert,this is how Firefox represents the bytes contained in the file. For a text fileit will simply output its text.
The getAsText(encoding)
method will return the contents as a string of bytesencoded depending on the encoding parameter. This is by default UTF-8, but theencoding parameter it's not really optional. You still have to pass some value.An empty string will do it just fine:
Finally, the getAsDataURL()
method, a very interesting and very useful one,will return the file contents in a format ideally suited for, let's say, the srcattribute of an IMG
tag. Of course, this will work as we're in Firefox rightnow, so let's add a IMG
tag to the HTMLsource and the appropriate JavaScript code to make this work:
More information about the new APIcan be found on their dedicated pages on Mozilla Developer Center:
Some extra information
You may wonder why an array of files for just one input element. It turns outthat RFC 1867, concerning form-basedfile uploads, specifies that a file input element allows its size attribute toreceive a complex value:
The SIZE
attribute might be specified using SIZE=width,height
,where width is some default for file name width, while height isthe expected size showing the list of selected files. For example,this would be useful for forms designers who expect to get severalfiles and who would like to show a multiline file input field inthe browser (with a 'browse' button beside it, hopefully). Itwould be useful to show a one line text field when no height isspecified (when the forms designer expects one file, only) and toshow a multiline text area with scrollbars when the height isgreater than 1 (when the forms designer expects multiple files).
None of the browsers I tested this in seems to obey the RFC,nevertheless this should be the reason for which the files property is anarray-like object.
The XMLHttpRequest object
Now that we're able to read local files, we need a way to get this data, over thenetwork, to the server. As we're aiming for an asynchronous data transmission,an XMLHttpRequest
object should do the job just fine. Unfortunately, its send()
method isn't that reliable in sending binary data. For this reason, along withthe local file access interface, Firefox 3 brought a new method to theXMLHttpRequest
object: sendAsBinary(data)
. Just as the send()
method, thenew one takes a single argument, a string, which is converted to a string ofsingle-byte characters by truncation (removing the high-order byte of eachcharacter), according to the documentation. The difference, a very importantone, is that, as long as send()
knows how to process anURL query string, sendAsBinary()
expects a totally different format in order to be useful for the server-side endof the application, but we'll talk about this a little bit later. Let's justwrite a little JavaScript skeleton, that we'll use when assembling together allthe pieces of the application:
As you see, there's an undefined variable in the above snippet, data, whichremains to be defined after we review the mechanism behind files upload overHTTP. For the moment though, Iwant to talk about the server-side part, as it will guide us in choosing theappropriate strategy for sending binary information.
The server-side script
PHP, as well as several web frameworks made on top of other languages, offersdifferent access points for reading POST data containing uploaded files and POSTdata containing just simple values. In PHP there are two predefined arrays givingyou access to simple POST data, the $_POST
array, and another one for accessingfiles sent to the server, the $_FILES
array. It is thus wise to build aclient-side script able to send information that PHP would read as from a classicalrequest issued with an HTML form:our uploaded files would appear as elements inside the $_FILES
array and additionalvalues as elements inside the $_POST
array. Under these circumstances we canwrite the PHP script to test that our JavaScript client is performing well:
That's all we need on the server. Although simple this we'll give us valuablefeedback about the sent data. The PHP script should list our uploaded filesinside the $_FILES
array and any additional form data (like text INPUT
orSELECT
element) inside the $_POST
array.
Clip studio paint 1.7.4 crack. – Change screen layouts flexibly, and register to use them anytime. – Palettes for finding a color that fits your image, in addition to the color set palette, color circle and color slider.
Form data over HTTP theory
As we saw, PHP treats POST-ed files differently than ordinary form field values,so it's only natural to ask ourselves what's the 'clue' that helps PHP tell apartone from the other.
First of all, every HTML formelement out there has an optional attribute called enctype, with a defaultvalue of application/x-www-form-urlencoded
. This is actually aMIME type valuespecifying the encoding to be used by the web browser when sending form data. Italso guides the web server script in decoding that data as the encoding is sentby the browser to the server in the form of an HTTPheader, called Content-Type
. For a default enctype value, form data is sent asASCIIcharacters, URL encoded when necessary.On the other hand, when uploading files, we need to change the enconding tomultipart/form-data
. Cloning this basic form functionality inside our JavaScriptclient is what we should do. Let's modify the earlier script so that it sendssuch a multipart/form-data
header:
RFC 1867, regarding form-based fileuploads, dictates that an extra parameter is required for the Content-Type
header when its value is multipart/form-data
. It is called boundary and itspresence it's very logical. The multipart word inside the header means the sentrequest is formed of multiple parts (obviously), so there must be something toseparate those parts. This thing is the boundary parameter which value must bea string of characters that shouldn't be found inside any of the form values wesend, otherwise the request will get garbled. Once again, let's modify the scriptto reflect this requirement.
Next, let's talk about the structure of the parts comprised in the request. Eachof these is like a little request on its own. Each has its own headers structureand body.
The mandatory header, every part must have, is called Content-Disposition
andits value should be form-data followed by an additional parameter called name,which represents the name of the form input that holds the data. In case of partsholding uploaded files, a second parameter must also be present, called filename.This is the name of the file as it was on the user's computer. Not the absolutepath, just the basename (for example, monkey.png). Parameter values are enclosedinside double quotes. A little example:
In the case of files, a second header must is also needed. It is calledContent-Type
and specifies the MIMEtype of the file. This may be deduced by reading the file extension or the sourceof the file. Anyway, a general value of application/octet-stream
is perfectlyacceptable:
As per the standards, every such header should end with two characters, acarriage return and a new line: CR
and LF
. The last header doubles thissequence (i.e. it ends with CRLFCRLF
).
Following the headers is the body which consists of the form field value. I'llillustrate with a simple text file upload, although it could be any type of file.The text inside the file is 'my random notes about web programming':
Finally I'll give you a final example with both the HTMLmarkup of the form as well as a fictional request from that form:
The issued request could be:
In case you didn't noticed, the boundary, when used in between the parts isprepended with two hyphens and the last one appended with also two hyphens. Don'tforget about this, it's an ugly source of bugs.
Encapsulating the JavaScript logic
At this point we know all the parts to successfully build a pure JavaScript fileuploader, which we're going to implement as an object. Here's the basic structureof the constructor and its prototype:
In case you didn't understand the elements()
construct, this is called a getterand is supported by the latest versions of Firefox, Opera, Safari and Chrome.A setter form is also provided. You can find more about these on Mozilla DeveloperCenter.
We should fill the above methods, so let's start with the send()
method becausewe already wrote much of it in a previous sections of the tutorial:
In addition to what we had earlier we have now introduced an iteration that allowsus to send additional headers without modifying the prototype itself. We have alsodefined the variable we talked about earlier, data, which holds the source of theHTTP request. It holds the valuereturned by a call to a method whose only purpose is to build anHTTP compliant request for fileuploads. Here's its source:
Although it looks complex, it has a fair amount of comments so that you won'thave hard times understanding what it does. It simply iterates over an array ofHTML elements and for each such anelement constructs a different message depending whether the element is a fileupload input or not. It pushes this message into an internal array, which isfinally joined using the boundary sent as an argument inside the send()
method.
Here follows the source of the elements()
getter, used in send()
:
The snippet above grabs all the INPUT
and SELECT
elements inside the FORM
element associated with the Uploader
object. These elements are eventuallyreturned into a unified array. There are, however no checks on these elements,like filtering disabled controls. Furthermore, the RFCspecifies that a client should send form data in the same order it was renderedin the user agent. For keeping the examples as short as I could, the method abovedoesn't take care of that, but the code inside the accompanying archive does.
The final piece of code left for presentation is the generateBoundary()
methodwhich must return a string unique in the body of our request. For our simpleexample though, the method below should be just fine:
Hasbi rabbi jallallah naat download. Zikr - National Taiwan University chorus. Telkom University Choir - Zikr (A.R. Mix - Hasbi Rabbi jallallah By Chinese choirYouTube. Hasbi Rabbi Jallallah - Duration: 5:41. Hasbi Rabbi jallallah By Chinese choir YouTube. New Naat 2018. Unsubscribe from New Naat. Sami Yusuf - Hasbi Rabbi| سامي يوسف - حسبي ربي| Live At Wembley Arena, UK in October 2007 from the DVD 'Live. Hasbi Rabbi Jallallah. PourChoeur Vokalensemble. (Thai Youth Choir 2015) - Duration: 3:00.
The code inside is building a string based on the current timestamp to which someother characters are prepended. I'm using the uppercased word 'AJAX' and some dashes,but this prefix isn't mandatory, the only condition that must be met is that theresult of generateBoudary()
should not appear anywhere else in out request exceptfor the boundary placeholders.
Finally, the headers property of our object remains like it was in the skeleton.It is there so that you can append additional headers to the request, for example:
Application Octet Stream Utf8
Save the source of the Uploader object in a file called 'uploader.js', we'll useit in a few moments.
Putting it all together
Let's now write the final HTMLsource and save it inside a file called 'index.html'. Aside the markup, the codebelow introduces some event listeners for the 'Upload' and 'Preview' button:
Now create another file, save it as upload.php, and write inside it the code wepresented in the server-side section of the tutorial:
That's all. You may now test the application, which will hopefully work from thefirst run. Don't forget to install Firebug to inspect what's happening behind thescenes.
Conclusion
There's probably a lot to be discussed around this new feature Mozilla introducedalong with Firefox 3. Some may wonder if it is worth using it. Well, as ever, itdepends on what you want to accomplish. You may employ fall back techniques (likethe iframe workaround) in order to have support for other browsers, if that isyour concern. If you want a fancy UI though,a Flash based uploader may be better. But don't forget, the newAPI is not all aboutuploading. You may now read local files and process them right there in thebrowser. You may resize images, parse XMLor do whatever your imagination limits are. In my opinion this is a huge stepforward for web development and I'd really like other browser vendors to implementthis API as the standardsseem to be abandoned. Rich Internet applications would be far more powerful andtheir responsiveness further increased.