demand
- Add Download Sample Button to the page
- To achieve a region can drag and drop upload word files, limit file size to 2MB and file type, display progress bar, and support canceling upload.
File download
What the business requires is that the sample be placed in a static folder without requiring a background request. For this scenario, the author will introduce three methods: window.open, form submission and a tag download. The author will compare the three methods by downloading img and word documents.
The structure of dom is constructed as follows:
<button onClick={this.windowOpen}>window.open</button> <button onClick={this.formSubmit}>formSubmit</button> <button onClick={this.aDownload}>aDownload</button>
Method 1: Use window.open:
import gakkiURL from './gakki.jpg'; import wordURL from './wordURL.doc'; windowOpen = () => { window.open(gakkiURL); //window.open(wordURL); }
When requesting two kinds of files, the method is shown as follows:
Img: Open a new web page, and then display the corresponding img pictures.
word: Download the file.
Method 2: Subit using form form:
formSubmit = () => { let form = document.createElement('form'); form.method = 'get'; form.action = gakkiURL; //form.action = wordURL; //Form. target ='_blank'; // form new page document.body.appendChild(form); // form forms are added to the dom tree before submitting form.submit(); document.body.removeChild(form); }
When requesting two kinds of files, the method is shown as follows:
img: form opens url and displays pictures on the current page when target is not set.
word: Download the file.
As can be seen from the above two methods, browsers will choose different processing methods for different MIME types when requesting the corresponding url. When requesting img, txt and other formats, the browser opens the corresponding file instead of downloading it. What if you want these formats to be downloaded as well? At this point, method three is needed.
Method 3: Using label a:
// Use a label aDownload = () => { const a = document.createElement('a'); a.href = gakkiURL; //a.href = wordURL; //a.download = 'gakki.jpg'; a.click(); }
The a tag performs the same two methods without the download attribute, and after adding the download attribute, it can successfully trigger the download of img and other formats.
download:
This property can set a value to specify the name of the download file. The allowable values are unlimited. The browser will automatically detect the correct file extension and add it to the file (.img,.pdf,.txt,.html, etc.).
The final comparative effect:
File drag and drop upload
File upload
The common method is to use the input tag of type="file" to trigger the download, and then use formData to transfer the data. The code is as follows:
// Click Upload Document handleClick = () => { const input = document.createElement('input'); input.type = 'file'; input.accept = 'application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document'; // MIME Types for word Files input.onchange = (e) => { const file = e.target.files.items(0);// files[0] will do as well. console.table(file); // Check document format if (!this.checkDocument()) { e.target.value = ''; return; } // Upload document this.uploadDocument(file); }; input.click(); };
accept: Indicates the MIME type of the file that input accepts. The MIME types corresponding to. doc and. docx are indicated in the source code.
fileList objects can be indexed by items or arrays to obtain the corresponding file objects. The common attributes of file objects are lastModified, type, name, and size. These attributes allow you to customize the document format.
The code checkDocument for checking documents is as follows:
// Document inspection checkDocument = file => { const accept = ['.doc', '.docx']; const index = file.name.lastIndexOf('.'); if (index < 0 || accept.indexOf(file.name.substr(index).toLowerCase()) < 0) { // Check file type Message.error('This file format is not supported for the time being.'); return false; } if (file.size > 2 * 1024 * 1024) { // Check file size Message.error('Documents greater than 2 MB,Upload failure'); return false; } return true; };
Then upload the document uploadDocument:
// Upload document uploadDocument = file => { const index = file.name.lastIndexOf('.'); const fileName = file.name.slice(0, index); const formData = new FormData(); formData.append('file', file); // Upload by ajax, fetch, axios, etc. ... };
After uploading the document, you need to get the progress bar of the upload progress display. The following sections describe the support of ajax, fetch and axios for the progress event respectively.
Ajax
Native support for progresses events can be used to obtain upload progress and download progress, respectively, xhr.upload.onprogress and xhr.onprogress events. The code is as follows:
xhr.upload.onprogress = ev => console.log((ev.loaded / ev.total) * 100)
In addition, you can use xhr.abort() to cancel file upload.
Fetch
Programs events are not supported, so upload progress cannot be retrieved. However, the author found that because res.body is a readable byte stream object, the download progress can be obtained by using the getReader() attribute supported by res.body object. Refer to the specific literature. jakearchibald.com/2016/stream… . The code here has nothing to do with the need for uploading, and can be skipped directly as an extension of fetch.
The res.body.getReader() method is used to read the original byte stream of the response, which can be read circularly until the body content transfer is completed.
fetch(url, options).then(res => { let reader = res.body.getReader(); let loaded = 0; // The read() method returns a promise and resolve s when the value is accepted. reader.read().then(function processResult(result) { // The result object has two attributes: // done: true at completion // value data if (result.done) { // Exit the loop at completion console.log("Fetch complete"); return; } loaded += result.value.length;// Length in bytes console.log('Received', loaded, 'bytes of data so far'); // Cyclic reading return reader.read().then(processResult); }); });
Axios
Upload and download are achieved through onUpload Progress and onDownload Progress.
onUploadProgress(ev) => { length = Math.round((ev.loaded / ev.total) * 100); console.log(length); }
axios cancels requests using cancel token
var CancelToken = axios.CancelToken; var source = CancelToken.source(); axios.get(url, { cancelToken: source.token }) source.cancel();//Cancellation request
summary
ajax and axios both support progresses events well, and fetch is not available here due to lack of support for progresses events.
Drag and drop events
After realizing the functions of clicking upload, getting upload progress and canceling upload, the next thing to be done is dragging upload. Before I implement this, I will introduce the relevant events. The first is the events that occur when dragging an object: onDragStart, onDrag and onDragEnd, which are related to the object being dragged.
onDragStart: Drag Start
onDrag: Continuous trigger in drag
onDragEnd: Drag ends, triggering events whether or not they can be placed
Then there are events to trigger when placing files: onDragEnter, onDragOver, onDragLeave and onDrop, which are related to the area to be dragged into.
onDragEnter: Triggered when a dragged object enters
onDragOver: Continuous triggering of dragged objects as they drag in the region
onDragLeave: Triggered when a dragged object leaves the area
onDrop: Triggered when a dragged object is placed in an area
In order to drag word documents in a project, you need to cancel the default onDragEnter and onDragOver events on the container because:
The event listener dragenter or dragover event is used to represent a valid drop target, where the drag item may be dropped. Most areas of a web page or application are not valid locations for drop data. Therefore, drop is not allowed by default processing of these events.
If you want to allow drop, you must prevent default processing by canceling events. You can do this by returning false from the attribute-defined event listener or by calling the preventDefault method of the event. The latter may be possible in a function defined in a separate script.
The dom structure is as follows:
<div styleName="dropbox" onDragOver={this.preventDefault} onDragEnter={this.preventDefault} onDrop={this.handleDrop} > <div styleName="word-img" /> {this.renderBtnByUpload(this.state.uploadStatus)} // Upload status determines whether to upload files or cancel uploads </div>
After dragging and dropping the file into the content area, the file information can be obtained through the dataTransfer object. The final handleDrop event is as follows:
// Drag and drop uploads handleDrop = (e) => { const file = e.dataTransfer.files[0]; if (e.dataTransfer.files.length > 1) { Message.error('Only one upload is supported word file'); return; } if (!this.checkDocument(file)) { // Upload failure exits directly e.target.value = ''; return; } this.uploadDocument(file); // Upload files }
summary
Ultimately, the overall idea of implementation is to build a container for placing files, then cancel the default onDragOver and onDragEnter events for the container, get the files and upload them through dataTransfer.files when dragging files into the container, take the length of the programs events provided by ajax or axios, transfer the length to the progress Bar component, and finally display them. Come out.
Links to the original text: https://www.jianshu.com/p/01c...