0

I'm struggling trying to upload two files to a php script and let the page download a new merged file without redirecting to a second page.

I don't want to cache any file on the server, because they could be large (2MB) binary files.

looking at this question:

Download a file by jQuery.Ajax

it seems that the jQuery File Upload plugin cannot handle uploads. There is an example posting a text. But it seems that file uploads don't pass through when the data gets serialized.

$(document).on("submit", "form.fileDownloadForm", function (e) {
    $.fileDownload($(this).prop('action'), {
        preparingMessageHtml: "We are preparing your report, please wait...",
        failMessageHtml: "There was a problem generating your report, please try again.",
        httpMethod: "POST",
        data: $(this).serialize()
    });
    e.preventDefault(); //otherwise a normal form submit would occur
});
denoise
  • 1,067
  • 2
  • 14
  • 40

2 Answers2

2

You can just add both files to a formData object, upload them with ajax and return the file

Something like

<form class="fileDownloadForm" method="POST"> 
    <input type="file" name="file1">
    <input type="file" name="file2"> 
    <input type="submit>
</form>

and then

$(document).on("submit", "form.fileDownloadForm", function (e) {
    e.preventDefault();

    $.ajax({
      url         : $(this).prop('action'),
      type        : "POST",
      data        : new FormData(this), // both inputs or "multiple" etc in same form
      processData : false,       // tell jQuery not to process the data
      contentType : false        // tell jQuery not to set contentType
    }).done(function( data ) {
      // return concatted file here as data from the server
    });
}

and return it

<?php    

    echo file_get_contents($_FILES['file1']) . file_get_contents($_FILES['file2']);

?>
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • The `php` portion would be accurate only for text files, yes? – guest271314 Jul 15 '17 at 21:20
  • Well, no, it would probably concat almost anything in PHP, but the returned result would just be gibberish to most humans ? – adeneo Jul 15 '17 at 21:22
  • Would `.` concatenate two `audio/*` or `video/*` files into a single file capable of playback at an `HTMLMediaElement`? – guest271314 Jul 15 '17 at 21:23
  • That is what meant at first comment. OP has not addressed any issue as to "merged" file, thus did not address that portion of Question at own Answer. – guest271314 Jul 15 '17 at 21:24
  • Oh okay. But ... `file_get_contents` is binary-safe, so it would return the binary as a string and concat it, it just probably wouldn't be a valid audio file anymore. – adeneo Jul 15 '17 at 21:26
  • Your Answer includes the pertinent `processData`, `contentType` settings for `$.ajax()`, though why include the `php` portion which will not return expected result for any file, and OP does not specially ask how to merge the files at `php`? – guest271314 Jul 15 '17 at 21:27
  • 1
    @guest271314 - it was just an example of how to access the files using `$_FILES` and the name etc. I leave merging the files up to the OP, as that depends entirely on what sort of files it is. The example works with text, but for binary one probably needs a library if wanting to join audio, video, images etc. – adeneo Jul 15 '17 at 21:30
  • It would be a beneficial feature of `php` if merging media files were that straight-forward [Proposal: Implement OfflineMediaContext #2824](https://github.com/whatwg/html/issues/2824) – guest271314 Jul 15 '17 at 21:32
  • It sure would. Jjoining binary files without some sort of library or convenient built in methods is almost impossible for most of us. Luckily there are such libraries for almost any file type, but having it built into PHP would be neat, even if I don't really use PHP. – adeneo Jul 15 '17 at 21:39
  • the "merging" part is actually a more complex operation in a binary file, this part is actually working. So, it's not a PHP question ;) – denoise Jul 15 '17 at 21:41
  • @denoise Then what is the Question? – guest271314 Jul 15 '17 at 21:43
  • @guest271314 the javascript part – denoise Jul 15 '17 at 21:44
  • And we've both answered that. Use a formData object, either by appending the files or using the appropriate form in your markup, send that formData object to the server, get the files, join them up, and just return the content. If the data is binary you may have to do something clientside to get it correctly as well – adeneo Jul 15 '17 at 21:47
1

You can use FormData() instance to post files to server using $.post() at change event of <input type="file">, at .then() offer download of merged file to user

var fd = new FormData();
var n = 0;
for (let file of e.target.files) {
  fd.append("files[" + n++ +"]", file);
}
$.post("/path/to/server", {files:fd})
.then(function(data) {
  // offer download of `data` here
})
guest271314
  • 1
  • 15
  • 104
  • 177
  • but this solution would require to upload the files and store the data in the server before the user clicks download – denoise Jul 15 '17 at 22:23
  • @denoise No. Only included the code that could be used to `POST` files to server within `change` event handler of `` element. adeneo code using `$.ajax()` is probably more appropriate using `processData:false`, `contentType:false` – guest271314 Jul 15 '17 at 23:39