vaadin / web-components

A set of high-quality standards based web components for enterprise web applications. Part of Vaadin 20+
https://vaadin.com/docs/latest/components
467 stars 83 forks source link

[upload] Support optional `FileReader` transport instead of `XMLHttpRequest` #1270

Open platosha opened 7 years ago

platosha commented 7 years ago

As a developer, I want the upload element to “upload” files with FileReader instead of XMLHttpRequest.

API idea:

<vaadin-upload transport="FileReader" method="text"></vaadin-upload>
<script>
  vaadinUpload.addEventListener('upload-success', function(e) {
    e.detail.xhr; /* `undefined` with FileReader transport */
    e.detail.fileReader; /* FileReader instance */
    e.detail.fileReader.result; /* text content of the “uploaded” file */
  });
</script>
platosha commented 7 years ago

Related issues: vaadin/vaadin-upload#90 vaadin/vaadin-upload#96 vaadin/vaadin-upload#127

stramel commented 7 years ago

Seems like this may also be able to encompass vaadin/web-components#1266

davidmaxwaterman commented 7 years ago

I'm a bit confused by this issue...I think it might be that the user wants to use FileReader() in place of the FormData(). I recently forked this repo in order to use an external FileReader, rather than the internal FormData(), so my use-case seems quite similar (if I've interpreted it correctly). I needed to read the file contents externally prior to uploading, so I didn't see the need for this element to read it again. This is what I ended up with :

@@ -710,17 +711,12 @@ Custom property | Description | Default
         }
       }.bind(this);

-      var formData = new FormData();
-
-      file.uploadTarget = this.target || '';
-      file.formDataName = this.formDataName;
+      file.uploadTarget = file.uploadTarget || this.target || '';
       var evt = this.fire('upload-before', {file: file, xhr: xhr}, {cancelable: true});
       if (evt.defaultPrevented) {
         return;
       }

-      formData.append(file.formDataName, file, file.name);
-
       xhr.open(this.method, file.uploadTarget, true);
       this._configureXhr(xhr);

@@ -735,9 +731,9 @@ Custom property | Description | Default

       // Custom listener could modify the xhr just before sending it
       // preventing default
-      evt = this.fire('upload-request', {file: file, xhr: xhr, formData: formData}, {cancelable: true});
+      evt = this.fire('upload-request', {file: file, xhr: xhr}, {cancelable: true});
       if (!evt.defaultPrevented) {
-        xhr.send(formData);
+        xhr.send(file.fileBuffer);
       }
     },

Note that the change to the file.uploadTarget assignment is because I needed to change the filename during upload-before, and that was overwriting it - it's not directly related to this issue, I think.

I assign to the file.fileBuffer property in order to pass in the contents of the file; otherwise, the changes are basically removing FormData().

Perhaps these changes can be generalised somehow.

stramel commented 7 years ago

@davidmaxwaterman

I don't understand the first change. Couldn't you set the uploadTarget in the upload-before event?

The second set of changes, you can prevent the default of upload-request and do your modification in your listener.

this.$.upload.addEventListener('upload-request', function(e) {
  e.preventDefault();
  e.detail.xhr.send(e.detail.file.fileBuffer);
});
LeongTitanFour commented 5 years ago

How can it store the array of image (base64) in the localstorage using vaadin-upload?

this.$.upload.addEventListener('upload-before', function(event) { const reader = new FileReader(); var dataImg = []; // var self = this; reader.onload = function(e) { for(var i = 0; i < maxFiles; i++) { dataImg.push({ data: reader[i], ImgBase: reader.result }) } localStorage.setItem('imageData',JSON.stringify(dataImg)); // self.set('imageStore.ImageData', dataImg); // localStorage.setItem('imageData', reader.result);

  }
  reader.readAsDataURL(event.detail.file);
});