Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse File Input for a second upload #86

Open
stefanocdn opened this issue May 13, 2016 · 5 comments
Open

Reuse File Input for a second upload #86

stefanocdn opened this issue May 13, 2016 · 5 comments
Labels

Comments

@stefanocdn
Copy link

I am trying to upload 2 different versions of the same file to AWS S3 from a single form: large and thumbnail.

The code for the upload is the following. The upload works fine and in the done callback I would like to start the second upload.

fileInput.fileupload({
        fileInput:       fileInput,
        url:             form.data('url'),
        type:            'POST',
        autoUpload:       true,
        formData:         form.data('form-data'),
        paramName:        'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
        dataType:         'XML',  // S3 returns XML if success_action_status is set to 201
        replaceFileInput: false,
        disableImageResize: false,
        imageMaxWidth: 800,
        imageMaxHeight: 800,
        imageCrop: true,

        done: function(e, data) {
          console.log('DONE');

          // HERE I WOULD LIKE TO MAKE A SECOND UPLOAD
          startThumbnailUpload();
        },
      });

The code for the startThumbnailUpload() method would be exactly the same except for the width and height:

function startThumbnailUpload(){
  fileInput.fileupload({
        fileInput:       fileInput,
        url:             form.data('url'),
        type:            'POST',
        autoUpload:       true,
        formData:         form.data('form-data'),
        paramName:        'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
        dataType:         'XML',  // S3 returns XML if success_action_status is set to 201
        replaceFileInput: false,
        disableImageResize: false,
        imageMaxWidth: 200,
        imageMaxHeight: 200,
        imageCrop: true,

        done: function(e, data) {
          console.log('DONE');
        },
   });
}

The second fileInput.fileupload never gets executed. Is there a way to achieve that kind of double upload with the same file reusing the same fileinput?

@felixbuenemann
Copy link
Collaborator

This repository is for the gem packaging of the jquery file upload gem.

However, just instantiating the plugin won't trigger a file upload, that's why your current code is doing nothing.

You should look into the Programmatic file upload section in the jQuery-File-Upload Wiki.

@stefanocdn
Copy link
Author

stefanocdn commented May 14, 2016

Thank you for the link, I checked out the Programmatic file upload section.
But there is a main problem I can't solve : I need to upload one file from 2 different widgets (I need these 2 different widgets to upload different sizes.

I tried to keep the code below and add a programmatic upload in the callback.

fileInput.fileupload({
        fileInput:       fileInput,
        url:             form.data('url'),
        type:            'POST',
        autoUpload:       true,
        formData:         form.data('form-data'),
        paramName:        'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
        dataType:         'XML',  // S3 returns XML if success_action_status is set to 201
        replaceFileInput: false,
        disableImageResize: false,
        imageMaxWidth: 800,
        imageMaxHeight: 800,
        imageCrop: true,

        done: function(e, data) {
          // Trigger a programmatic upload
          fileInput.fileupload('send', {
            fileInput:       fileInput,
            url:             form.data('url-thumbnail'),
            type:            'POST',
            formData:         form.data('form-data-thumbnail'),
            paramName:        'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
            dataType:         'XML',  // S3 returns XML if success_action_status is set to 201
            replaceFileInput: true,
            disableImageResize: false,
            singleFileUploads: false,
            imageMaxWidth: 100,
            imageMaxHeight: 100,
            imageCrop: true})
          .success(function (result, textStatus, jqXHR) {
            console.log("SUCCESS");
          })
          .error(function (jqXHR, textStatus, errorThrown) {
            console.log("error");
          })
          .complete(function (result, textStatus, jqXHR) {
            console.log("complete");
          });
        },
      });

Which enters a loop of uploads. Not working.

Then I thought about creating 2 different widgets to upload programmatically following the pattern:

//Initialize
$('#file').fileupload({
  url: 'thumbnailURL'
});
$('#form').fileupload({
  url: 'largeURL'
});

//Trigger the submit
$('#file').fileupload({
  fileInput: $('#file')
});
$('#form').fileupload({
  fileInput: $('#file')
});

But the 2 widgets end up referring to the same file input and that doesn't work either.

I thought about an hacky solution, add a second hidden file input, create a second separate widget, and then populate the input field when the file is selected : but it is not possible to populate manually an input field with a file.

Unfortunately I can't think of another way to proceed..
Any suggestion or idea would be of great help!

@stefanocdn
Copy link
Author

I am trying another approach for the multiple versions upload.

The following code works fine.

$('#file_upload').find("input:file").each(function(i, elem) {
  var fileInput    = $(elem);
  var form         = $(fileInput.parents('form:first'));
  fileInput.fileupload({
    fileInput:       fileInput,
    url:             form.data('url'),
    type:            'POST',
    autoUpload:       true,
    formData:         form.data('form-data'),
    paramName:        'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
    dataType:         'XML',  // S3 returns XML if success_action_status is set to 201
    replaceFileInput: false,
    disableImageResize: false,    imageCrop: true,
    processQueue: [
          {
              action: 'loadImage',
              fileTypes: /^image\/(gif|jpeg|png)$/,
              maxFileSize: 20000000 // 20MB
          },
          {
              action: 'resizeImage',
              maxWidth: 400,
              maxHeight: 400
          },
          {action: 'saveImage'}
      ],
      processstart: function (e) {
          console.log('Processing started...');
      },
      process: function (e, data) {
          console.log('Processing ' + data.files[data.index].name + '...');
      },
      processdone: function (e, data) {
          console.log('Processing ' + data.files[data.index].name + ' done.');
      }
  }); //fileupload

I changed the processQueue to upload 2 versions in a row:

processQueue: [
          {
              action: 'loadImage',
              fileTypes: /^image\/(gif|jpeg|png)$/,
              maxFileSize: 20000000 // 20MB
          },
          {
              action: 'resizeImage',
              maxWidth: 400,
              maxHeight: 400
          },
          {action: 'saveImage'},
          {action: 'duplicateImage'},
          {
              action: 'resizeImage',
              maxWidth: 200,
              maxHeight: 200
          },
          {action: 'saveImage'},
      ]

Problem: the first saveImage does not upload the first image before duplicating. Instead there is only one POST request issued for both files, which returns the error => POST requires exactly one file upload per request.

Any idea how to fix this issue? Thx for your help.

@felixbuenemann
Copy link
Collaborator

Shouldn't you be able to use fileupload('add', options) or fileupload('send', options) twice to do the upload? You could then set the different image sizes in the options hash. You might need to set replaceFileInput: false for this to work.

@stefanocdn
Copy link
Author

@felixbuenemann Thanks again for your reply.
fileupload('add', options) does not work for me because I trigger the upload already inside an add callback so then it loops.
Using fileupload('send', options) works fine for the upload, and I can trigger it twice which is perfect, but I can't get any resize working : the original is uploaded every time.

fileInput.fileupload('send',
{
  fileInput: fileInput,
  url: form.data('url'),
  disableImageResize: false,
  imageCrop: true,
  imageMaxWidth: 100,
  imageMaxHeight: 100,
  formData: data_thumbnail,
  replaceFileInput: false,
  type:            'POST',
  autoUpload:       false,
  paramName:        'file',
  dataType:         'XML'
  }
);

I could not fine SO threads mentioning resizing with 'send' and I could not find it in the wiki either, so if you have the solution to resize with 'send' that would be extremely helpful. Thanks again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants