0

I want to make a file input where you can select an image then it display within a specific div. I've tried a few methods I've seen and I have done this in the past but I don't remember... I want to do that with a text document as well, just displaying the text without an iframe or anything.

Any pointers?

Just so you know I want to put in local files and it is only required to work in chrome.

Fin
  • 353
  • 3
  • 5
  • 16
  • 1
    you need to check the `FileReader` and `readAsDataURL `. This answer have good example how you can use it - http://stackoverflow.com/questions/16430016/using-readasdataurl-for-image-preview – Alisher Gafurov Apr 04 '17 at 09:19

3 Answers3

0

$(document).ready(function(){

     $('input.upload').on('change', addFile);
    
});

     function addFile (event) {

        var jqDisplay = $('div.myTarget');
        var reader = new FileReader();
        var selectedFile = event.target.files[0];

        reader.onload = function (event) {
            var imageSrc = event.target.result;
            jqDisplay.html('<img src="' + imageSrc + '" alt="uploaded Image">');
        };
       reader.readAsDataURL(selectedFile); 
    }
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
</head>
<body>

  <div class="myTarget"></div>
  <input type="file" class="upload">

</body>
</html>
  • This doesn't handle text files, it does useless parsing of the file path, when the File object has a `name` property, and it uses a FileReader, when it is not necessary... – Kaiido Apr 06 '17 at 04:26
  • The parsing for the file path was an useful old part of my script, where i copied this part of code. Text file parsing was no target in my script. The file reader is needed here. – Tobias Sattler Apr 06 '17 at 10:21
  • But here you are answering a question. The parsing of the file path is useless for this question. And if you need the file's name, check its `name` property. Text file parsing is a requirement of the question. The FileReader is not needed in your script, which handles only image, check [my own answer](http://stackoverflow.com/a/43246085/3702797) where I explain that one should prefer the URL.createObjectURL method. – Kaiido Apr 06 '17 at 11:52
0

Well, it is based on javascript approach of handling the upload, so in angular2, I upload the image in the following way using typescript..Th input type file is the key here.

The src is binded by a property whose value is set inside the code with the returned aws s3 url provided by the server response, when I send him the image url to save it.

The html :-

<div class="mt-10 fileUpload">
          <label class="uploadBtnLabel bm-action-btn">
            <input type="file" name="resourceFile" #uploadElem accept="image/*" (change)="uploadImage(submitElem)"/>
            <input type = "submit" id="fileUpload" class="hidden" name="fileUpload" #submitElem (click)="store.postFileUpload(uploadElem, group)">
            <span>Upload<i class=" pl-5 fa fa-upload"></i></span>
          </label>
        </div>

<img class="logoImage" [src]="group.controls['logoUrl'].value" *ngIf="group.controls['logoUrl'].value">

The typescript functions for the same to convert the image into dataUrl and send it to the server.

//Function to upload local file
    uploadImage(submitElem, renderer){
        let event = new MouseEvent('click', {bubbles: false});
        renderer.invokeElementMethod(
          submitElem, 'dispatchEvent', [event]);
      }

  postFileUpload(inputValue, group){
    this.readImage(inputValue, group);
  }

  readImage(inputValue: any, group): void {
    if(inputValue) {
      let image;
      let self = this;
      let accountId;
      var file: File = inputValue.files[0];
      var myReader: FileReader = new FileReader();
      myReader.readAsDataURL(file)
      myReader.onloadend = (e) => {
        image = myReader.result.split(',')[1];
        let postData = {
          imageString: image
        };
        if(group.controls['accountId']) {
          accountId = group.controls['accountId'].value;
        }else{
          accountId = self.mssId;
        }
        self.imageUploadSub = self.invoiceConfService.uploadImage(accountId, postData).subscribe(
          (response) => {
            group.controls['logoUrl'].setValue(response.data.logoUrl);
            self.imageLink = response.data.logoUrl;
          },
          (error) => {
          });
      }
    }
  }
Community
  • 1
  • 1
Gaurav Pandvia
  • 805
  • 7
  • 13
  • damn that looks complex – Fin Apr 04 '17 at 09:38
  • I put that in but it doesn't look right. Where you have the HTML in the img part is showing up as white from the src attribute onwards and when I input an image nothing happens, anything I need other than html/javascript? – Fin Apr 04 '17 at 09:42
0

You don't need to use a FileReader to display a user uploaded File.
readAsDataURL is relatively expansive. It forces you to keep 130% of the original file size, directly in the HTML markup, and thus, it represents a big increase in your memory consumption.

Instead, you should always prefer URL.createObjectURL method when dealing with user uploaded files. This will only store a direct pointer to the file on the user's system, and returns a small URI : memory impact almost null.

However, you stated that you didn't want to use iframes, this is unfortunate since it is one of the only elements which can display text files from an html page.
So for this, case, you will have to use a FileReader, but use the readAsText() method.

So here is a naïve universal media player :

f.onchange = function(e) {
  let file = this.files[0];
  let elementType;
  // this is really naïve, the MIME type means nothing and should not be trusted
  let fileType = file.type.split('/')[0];
  switch (fileType) {
    // determine which element to create
    case 'image': elementType = 'img'; break;
    case 'video': elementType = 'video'; break;
    case 'audio': elementType = 'audio'; break;
    case 'text': // this one may break and should not be there
      elementType = 'pre';
      break;
    default: // We'll use an iframe for unknow elements
      elementType = 'iframe'; break;
  }

  let elem = document.createElement(elementType);
  if (elementType !== 'pre') { // a real media
    // not really needed here,
    // but it's always good to revoke a blobURI when not needed anymore
    elem.onload = e=> { URL.revokeObjectURL(elem.src) };

    elem.src = URL.createObjectURL(file);
    if(elementType === 'audio' || elementType === 'video'){
      elem.controls = true;
      }
  } else {
    // so we said we wanted to display text files inside the current document ...
    let reader = new FileReader();
    reader.onload = function() {
      elem.textContent = reader.result;
    };
    reader.readAsText(file);
  }
  document.body.appendChild(elem);
}
iframe {
  border: none;
}
<input type="file" id="f">
Kaiido
  • 123,334
  • 13
  • 219
  • 285