All types of files can be uploaded, but forms cannot be uploaded.

Source: Internet
Author: User

[Switch] various forms that are indispensable for file uploads and forms for file uploads

[Switch] forms that are inseparable from various file uploads

As programmers, we often need to use the file upload and download functions. When necessary, various types of information are queried. There are wood .... For the convenience of next use, here is a summary and memo.

Use forms to upload files

The most primitive, simple, and crude file upload.
Front-end code:

// Method 1 <form action = "/Home/SaveFile1" method = "post" enctype = "multipart/form-data"> <input type = "file" class = "file1 "name =" file1 "/> <button type =" submit "class =" but1 "> upload </button> </form>

Note]

  • 1. post submission required
  • 2. enctype = "multipart/form-data" (Transfer File)
  • 3. The name attribute must be set for the form element to be submitted.

Background code:

Public ActionResult SaveFile1 () {if (Request. Files. Count> 0) {Request. Files [0]. SaveAs (Server. MapPath ("~ /App_Data/") + Request. Files [0]. FileName); return Content (" saved successfully ");} return Content (" file not read ");}
Asynchronous form upload (jquery. form plugin)

Although the above method is simple and rude, It is not friendly enough. The page will inevitably be refreshed. It is difficult to stay on the current page and give a prompt that the file is uploaded successfully.
With the passage of time, technology is changing with each passing day. The emergence of ajax makes asynchronous file submission easier.
Next we will use the jquery. form plug-in to implement asynchronous file upload.
First, we need to importjquery.jsAndjquery.form.js
Front-end code:

<Form id = "form2" action = "/Home/SaveFile2" method = "post" enctype = "multipart/form-data"> <input type = "file" class =" file1 "name =" file1 "/> <button type =" submit "class =" but1 "> upload 1 </button> <button type =" button "class =" but2"> upload 2 </button> </form>
// Method 2 (binding ajax through ajaxForm) $ (function () {$ ('# form2 '). ajaxForm ({success: function (responseText) {alert (responseText) ;}}); // method 3 (directly execute ajax operations through ajaxSubmit) $ (function () {$ (". but2 "). click (function () {$ ('# form2 '). ajaxSubmit ({success: function (responseText) {alert (responseText );}});});});

Background code:

Public string SaveFile2 () {if (Request. Files. Count> 0) {Request. Files [0]. SaveAs (Server. MapPath ("~ /App_Data/") + Path. GetFileName (Request. Files [0]. FileName); return" saved successfully ";} return" Not Read File ";}

Principle:
We often use plug-ins, regardless of other plug-ins.
If you are curious, think about how this plug-in is implemented. I casually looked at the source code over one thousand five hundred lines. My mom, isn't it an asynchronous upload? Why is it so complicated.
It's hard to see what the ghost is. Let's debug the breakpoint directly.

In the original plug-in, iframe and FormData are uploaded in different ways to adapt to more browsers.

Simulate form data upload (FormData)

Iframe is disgusting. We can see that FormData can be used to upload files, which is only available in Html 5. Next let's try it on our own.
Front-end code:

<Input id = "fileinfo" type = "file" class = "notFormFile"/> <button type = "button" class = "btnNotForm"> upload 4 </button>
// Method 4 $ (". btnNotForm "). click (function () {var formData = new FormData (); // initialize a FormData object formData. append ("files", $ (". notFormFile ") [0]. files [0]); // inserts the file into FormData $. ajax ({url: "/Home/SaveFile2", type: "POST", data: formData, processData: false, // tell jQuery not to process the sent data contentType: false, // tell jQuery not to set the Content-Type Request Header success: function (responseText) {alert (responseText );}});});

Code after: (unchanged, or the code above)

Public string SaveFile2 () {if (Request. Files. Count> 0) {Request. Files [0]. SaveAs (Server. MapPath ("~ /App_Data/") + Path. GetFileName (Request. Files [0]. FileName); return" saved successfully ";} return" Not Read File ";}

We can see that the FormData object is only simulating data in the original form format. Is it possible not to use form or Form format to upload files? The answer is yes. (As shown below)
Front-end code:

<Input type = "file" id = "file5" multiple> <button type = "button" class = "btnFile5"> upload 5 </button>
// Method 5 $ (". btnFile5 "). click (function () {$. ajax ({url: "/Home/SaveFile4", type: "POST", data: $ ("# file5") [0]. files [0], processData: false, // tell jQuery not to process the sent data contentType: false, // tell jQuery not to set the Content-Type Request Header success: function (responseText) {alert (responseText );}});;});

Background code:

Public string SaveFile4 () {// only one network stream can be obtained here, with no other information. Request. SaveAs (Server. MapPath ("~ /App_Data/SaveFile4.data ") +" ", false); return" saved successfully ";}

If you find that no form format is available, you cannot tell other information (such as file format) in the background except for uploading file stream data ).
At this point, I seem to understand why a form must be used to package the uploaded files. It turns out that this is just a transfer format agreed with the background.
In fact, when we use jq ajax to transmit text data, we finally assemble the data in form format, such:

$. Ajax ({data: {"userName": "Zhang San "}
Multipart upload

After learning about the various uploads above, are we full of the status quo? No. In many cases, we need to transmit large files. Generally, the server has a certain size limit.
One day, you found a passionate little movie to share with everyone. What should I do if the HD file is too big to be uploaded? We can convert it to zero. Part of the data is uploaded, that is, multipart upload.
Front-end code:

<Input type = "file" id = "file6" multiple> <button type = "button" class = "btnFile6"> multipart upload 6 </button> <div class = "result "> </div>
// Method 6 $ (". btnFile6 "). click (function () {var upload = function (file, skip) {var formData = new FormData (); // initialize a FormData object var blockSize = 1000000; // The size of each block var nextSize = Math. min (skip + 1) * blockSize, file. size); // read to the end position var fileData = file. slice (skip * blockSize, nextSize); // captures some file blocks formData. append ("file", fileData); // inserts some files into FormData formData. append ("fileName", file. name); // save the file name $. ajax ({url: "/Home/SaveFile6", type: "POST", data: formData, processData: false, // tell jQuery not to process the sent data contentType: false, // tell jQuery not to set the Content-Type Request Header success: function (responseText) {$ (". result "Upload .html (" uploaded "+ (skip + 1) +" Block file "); if (file. size <= nextSize) {// If the upload is complete, the system jumps out and continues to upload alert ("uploaded"); return;} upload (file, ++ skip ); // recursive call}) ;}; var file =$ ("# file6") [0]. files [0]; upload (file, 0 );});

Background code:

Public string SaveFile6 () {// save the file to the root directory App_Data + get the file name and format var filePath = Server. MapPath ("~ /App_Data/") + Request. form ["fileName"]; // create an append (FileMode. append) mode file stream using (FileStream fs = new FileStream (filePath, FileMode. append, FileAccess. write) {using (BinaryWriter bw = new BinaryWriter (fs) {// read the file stream BinaryReader br = new BinaryReader (Request. files [0]. inputStream); // convert the object into a byte array byte [] bytes = br. readBytes (int) Request. files [0]. inputStream. length); // append the byte array to the file bw. write (bytes) ;}} return "saved successfully ";}

Relatively speaking, the amount of code is a little more complicated. However, it should be much simpler than other multipart upload code on the Internet (because multipart upload and resumable upload are not considered here. In this way, you need to sort the file blocks in the background, upload and merge the files in order, and then delete the original temporary files. If you are interested, you can try it on your own. It will be implemented when the webuploader plug-in is analyzed and uploaded later ).
:

[Note]: What if we want to upload multiple files? In fact, H5 also provides a very simple method. Directly ininputMarkmultiple,<input type="file" id="file6" multiple>Then we receive an array in the background.Request.Files.

Use HTML5 to drag and drop, paste and upload

It can only be said that H5 is really powerful, with more and more permissions and more powerful operations.
Front-end code (drag and drop upload ):

<Textarea class = "divFile7">// Method 7 $ (". divFile7 ") [0]. ondrop = function (event) {event. preventDefault (); // do not execute the default action var files = event. dataTransfer. files; // get the dragged file // the following code remains unchanged var formData = new FormData (); // initialize a FormData object formData. append ("files", files [0]); // inserts the file into FormData $. ajax ({url: "/Home/SaveFile2", type: "POST", data: formData, processData: false, // tell jQuery not to process the sent data contentType: false, // tell jQuery not to set the Content-Type Request Header success: function (responseText) {alert (responseText );}});};

Background code:
(Same as the previous SaveFile2)

Front-end code (paste upload limit image format ):

// Method 8 $ (". divFile7 ") [0]. onpaste = function (event) {event. preventDefault (); // do not execute the default action var clipboard = event associated with the event. clipboardData. items [0]; // if (clipboard. kind = 'file' | clipboard. type. indexOf ('image')>-1) {// determines the image format var imageFile = clipboard. getAsFile (); // get the file // the following code remains unchanged var formData = new FormData; formData. append ('files', imageFile); formData. append ('filename', "temp.png"); // name the file (or name it when it is saved in the background) $. ajax ({url: "/Home/SaveFile8", type: "POST", data: formData, processData: false, // tell jQuery not to process the sent data contentType: false, // tell jQuery not to set the Content-Type Request Header success: function (responseText) {alert (responseText );}});}};

Background code:

Public string SaveFile8 () {// save the file to the root directory App_Data + get the file name and format var filePath = Server. MapPath ("~ /App_Data/") + Request. form ["fileName"]; if (Request. files. count> 0) {Request. files [0]. saveAs (filePath); return "saved successfully";} return "Not Read File ";}


Upload plug-in (WebUploader)

I have listed and analyzed multiple methods for uploading files. I think there is always one method that suits you. However, the upload function is quite common, and we may not consider many of the situations we write on our own. Next, we will briefly introduce Baidu's WebUploader plug-in.
Compared with our own simple upload, it has advantages: stable and compatible (with flash switching, so it supports IE) multi-function, concurrent upload, and resumable upload (mainly relying on background cooperation ).
Official Website: http://fex.baidu.com/webuploader/
Plug-in download: https://github.com/fex-team/webuploader/releases/download/0.1.5/webuploader-0.1.5.zip
The following describes how to use WebUploader:
First, simple and crude
Front-end code:

<Div id = "picker"> select file </div> <button id = "ctlBtn" class = "btn-default"> Start upload </button>
<! -- Reference webuploader's js and css --> <link href = "~ /Scripts/webuploader-0.1.5/webuploader.css "rel =" stylesheet "/> <script src = "~ /Scripts/webuploader-0.1.5/webuploader. js "> </script> <script type =" text/javascript "> var uploader = WebUploader. create ({// (if a new browser does not need flash) // swf: '/Scripts/webuploader-0.1.5/Uploader.swf', // file receiving server. Server: '/Webuploader/savefile', // select the file button. Optional. // The internal operation is based on the current operation, which may be an input element or flash. pick: '# picker'}); $ ("# ctlBtn "). click (function () {uploader. upload () ;}); uploader. on ('uploadsuccess', function (file) {alert ("uploaded successfully") ;}); </script>

Background code:

Public string SaveFile () {if (Request. Files. Count> 0) {Request. Files [0]. SaveAs (Server. MapPath ("~ /App_Data/") + Path. GetFileName (Request. Files [0]. FileName); return" saved successfully ";} return" Not Read File ";}

Second, multipart upload. It is similar to what we wrote before.
Front-end code:

Var uploader = WebUploader. create ({// compatible with older IE swf: '/Scripts/webuploader-0.1.5/Uploader.swf', // file receiving server. Server: '/Webuploader/svefile2', // enable multipart upload. Chunked: true, // chunkSize: 1000000, // number of concurrent uploads threads: 1, // select the file button. Pick: '# picker'}); // click to trigger upload $ ("# ctlBtn "). click (function () {uploader. upload () ;}); uploader. on ('uploadsuccess', function (file) {alert ("uploaded successfully ");});

Background code:

Public string SveFile2 () {// save the file to the root directory App_Data + get the file name and format var filePath = Server. MapPath ("~ /App_Data/") + Path. getFileName (Request. files [0]. fileName); // create an append (FileMode. append) mode file stream using (FileStream fs = new FileStream (filePath, FileMode. append, FileAccess. write) {using (BinaryWriter bw = new BinaryWriter (fs) {// read the file stream BinaryReader br = new BinaryReader (Request. files [0]. inputStream); // convert the object into a byte array byte [] bytes = br. readBytes (int) Request. files [0]. inputStream. length); // append the byte array to the file bw. write (bytes) ;}} return "saved successfully ";}

We see a parameter.threads: 1The number of concurrent uploads. What if we change to 1 or more? Multiple File slices are uploaded at the same time. An error is reported in the background. Multiple processes operate on one file at a time.
What if we want multi-thread upload? Change the code (mainly the background logic ).
Front-end code:

// Concurrent upload (multi-threaded upload) var uploader = WebUploader. create ({// compatible with older IE swf: '/Scripts/webuploader-0.1.5/Uploader.swf', // file receiving server. Server: '/Webuploader/svefile3', // enable multipart upload. Chunked: true, // chunkSize: 1000000, // number of concurrent uploads threads: 10, // select the file button. Pick: '# picker'}); // click to trigger upload $ ("# ctlBtn "). click (function () {uploader. upload () ;}); uploader. on ('uploadsuccess', function (file) {// After the upload is complete, send a command for merging files to the background $. ajax ({url: "/Webuploader/FileMerge", data: {"fileName": file. name}, type: "post", success: function () {alert ("uploaded successfully ");}});});

Background code:

Public string SveFile3 () {var chunk = Request. Form ["chunk"]; // The number of var paths = Server. MapPath ("~ /App_Data/") + Path. GetFileNameWithoutExtension (Request. Files if (! Directory. exists (path) // determines whether this path Exists. If not, create {Directory. createDirectory (path);} // save the file to the root directory App_Data + get the file name and format var filePath = path + "/" + chunk; // create an append (FileMode. append) mode file stream using (FileStream fs = new FileStream (filePath, FileMode. append, FileAccess. write) {using (BinaryWriter bw = new BinaryWriter (fs) {// read the file stream BinaryReader br = new BinaryReader (Request. files [0]. inputStream); // convert the object into a byte array byte [] bytes = br. readBytes (int) Request. files [0]. inputStream. length); // append the byte array to the file bw. write (bytes) ;}} return "saved successfully ";}
/// <Summary> /// merge the file /// </summary> /// <param name = "path"> </param> /// <returns> </returns> public bool FileMerge () {var fileName = Request. form ["fileName"]; var path = Server. mapPath ("~ /App_Data/") + Path. getFileNameWithoutExtension (fileName); // The string must be sorted correctly and converted to a number (the string will be sorted by 1 10 11, and the default value is 10 to 2) foreach (var filePath in Directory. getFiles (path ). orderBy (t => int. parse (Path. getFileNameWithoutExtension (t) {using (FileStream fs = new FileStream (Server. mapPath ("~ /App_Data/") + fileName, FileMode. append, FileAccess. write) {byte [] bytes = System. IO. file. readAllBytes (filePath); // read the file to the byte array fs. write (bytes, 0, bytes. length); // Write File} System. IO. file. delete (filePath);} Directory. delete (path); return true ;}

Do you think it's over now? Wrong, there are still many situations not taken into account. What if the file name uploaded by multiple users is the same? How to Implement resumable data transfer? Haven't multiple files been selected yet? However, I am not going to paste the code here. (I will paste the code more frequently.) I will also practice it myself.
Provide an idea to insert a piece of data into the database before uploading. Data contains the path, file name to be stored in the file (named with GUID to prevent conflict with files of the same name), file MD5 (used to identify next resume and second transfer) temporary File Block Storage path, whether the file is successfully uploaded, and other information.
If the file is uploaded after the network is disconnected, obtain the MD5 value of the file first, and check that there are files not uploaded in the database. If yes, the file will be uploaded in seconds. If not, check whether the part has been uploaded. If there is a next upload, if not, re-upload a new file.

Summary

I have been wondering why the form package must be used to upload files. Now I understand it.
When javascript is not streaming, we can directly use the submit button to submit the form data. The form can contain text and files. With the popularity of js and ajax, ajax can be used to directly submit some form data asynchronously. At the beginning, I am confused about why ajax can submit self-assembled data. Why can't I directly submit a file. I am wrong here. ajax does not submit arbitrary data, but is finally assembled into the form format (because the background technology supports the Form format data more widely ). However, the existing technology cannot assemble a form data in file format through js. Until FormData in H5 appears, it is possible for the front-end js to assemble a form format data containing files. Therefore, the form is only used to meet the "agreed" data format with the background.

 

Related Recommendations

  • Http://www.cnblogs.com/fish-li/archive/2011/07/17/2108884.html
  • Http://javascript.ruanyifeng.com/htmlapi/file.html

Demo

  • Https://github.com/zhaopeiym/blogdemocode/tree/master/upload and download

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.