6

I have unsuccessfully been trying to send a Blob file (which is an .OBJ file type) to the server using AJAX. I want to be able to do this without using an input file field. I am making an online avatar creator, so the Blob file to be sent to the server is generated from the character that is initially imported into my Three.js scene. I have been able to send a Blob file that contains a String to the server and save this to a specified folder (which I am aiming to do with the Blob .OBJ file). I have tried converting the Blob to Base64 before sending it in a POST request, but this did not work. The size of the file that I am trying to send is 3MB.

Here is my JavaScript code for creating the Blob file and sending it to my PHP script on the server using AJAX.

//Create OBJ
var exporter = new THREE.OBJExporter();
var result = exporter.parse(child);

//Generate file to send to server
var formData = new FormData();
var characterBlob = new Blob([result], {type: "octet/stream"});

var reader = new FileReader();
reader.readAsDataURL(characterBlob);
reader.onloadend = function() {
formData.append('file', reader.result);

    $.ajax({
    url: "ExecuteMaya.php", // Url to which the request is send
    type: "POST",             // Type of request to be send, called as method
    data: formData, // Data sent to server, a set of key/value pairs (i.e. form fields and values)
    processData:false,        // To send DOMDocument or non processed data file it is set to false
    contentType: false,       // The content type used when sending data to the server
    }).done(function(data) {
        console.log(data);
    });
}

Here is my PHP script for handling the sent file.

<?php

$sourcePath = $_FILES['file']['tmp_name'];       // Storing source path of the file in a variable
$targetPath = "upload/".$_FILES['file']['name']; // Target path where file is to be stored
move_uploaded_file($sourcePath,$targetPath) ;    // Moving Uploaded file
echo "<span id='success'>Image Uploaded Successfully...!!</span><br/>";
echo "<br/><b>File Name:</b> " . $_FILES["file"]["name"] . "<br>";
echo "<b>Type:</b> " . $_FILES["file"]["type"] . "<br>";
echo "<b>Size:</b> " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "<b>Temp file:</b> " . $_FILES["file"]["tmp_name"] . "<br>";

?>

Any help would be much appreciated!

UPDATE 1: The var result = exporter.parse(child); is a String and whenever I print this variable to the console it takes a few minutes to load. Would the size of this String be a possible issue with trying to send it to the server?

UPDATE 2: This gets printed to the console after the PHP script has been executed, which makes me think that either nothing is being sent over to the server or the sent data is not being handled correctly by the PHP script.

Image Uploaded Successfully...!!

File Name:
Type:
Size: 0 kB
Temp file:

UPDATE 3: Here is a link to the file that I am trying to send. http://www.filehosting.org/file/details/578744/CleanFemaleOBJ.obj

You can view this file in TextEdit/NotePad to view the String that I want to send. It is pretty much a text file with the .obj extension to convert it to that format so it can be opened in Maya.

UPDATE 4: I have now altered my JavaScript code so that the Blob is appended to the FormData and not the result of reader.readAsDataURL(characterBlob).

//Create OBJ
var exporter = new THREE.OBJExporter();
var result = exporter.parse(child);

//Generate file to send to server
var formData = new FormData();
var characterBlob = new Blob([result], {type: "octet/stream"});
formData.append('file', result);                            

    $.ajax({
    url: "ExecuteMaya.php", // Url to which the request is send
    type: "POST", // Type of request to be send, called as method
    data: formData, // Data sent to server, a set of key/value pairs (i.e. form fields and values)
    processData: false, // To send DOMDocument or non processed data file it is set to false
    }).done(function(data) {
        console.log(data);
    });
skelto
  • 157
  • 1
  • 11
  • 1
    `reader.result` is a data uri not a blob/file, you should be sending `characterBlob` instead – Musa Jun 17 '16 at 11:43
  • @Musa I originally tried sending characterBlob but this did not work. Whenever I send the characterBlob I get a message in my console to say it was sent successfully, but no file appears in the folder that I am saving the Blob file to. – skelto Jun 17 '16 at 11:56
  • @Musa would you know how to resolve this issue? – skelto Jun 17 '16 at 14:11
  • Print out also `$_FILES["file"]["error"]`. What [value](http://php.net/manual/en/features.file-upload.errors.php) does it return? If the string is not too long, edit your post with the string that is displayed (UPDATE 1). – Mikey Jun 20 '16 at 13:18
  • @Mikey I am getting no return value for $_FILES["file"]["error"] much like when I try to echo other information about the file. Is my PHP script incorrect? I have now updated my question to include a link to the .OBJ file, thanks. – skelto Jun 20 '16 at 14:07
  • That's weird. I would expect some number at least to be given to you. Double-check that you properly echo'd `$_FILES["file"]["error"]`. As @Musa mentioned, you may be sending a data URI -- therefore you probably need to look at your [$_POST](http://stackoverflow.com/questions/6735414/php-data-uri-to-file). – Mikey Jun 20 '16 at 15:13
  • @Mikey I've added an 'UPDATE 4' to show the JavaScript I am currently working with. I have tried both 'echo $_POST['file'];' and 'echo $_FILES['file']['tmp_name']' and nothing shows up in the console. I'm guessing it could be because it's taking a while for it to load. I have left it for a few minutes and still nothing shows up in the console. When I then try to close/reload the window, the page either crashes or takes a while to close/reload. This makes me think it is still trying to load the echo to the console. – skelto Jun 20 '16 at 15:42
  • It looks like you have mistaken with this line: `formData.append('file', result);`. It should be `formData.append('file', characterBlob);`. Also try to add `contentType: false` to your AJAX call – Oleg Jun 21 '16 at 14:19
  • @Curious doesn't seem to have changed anything but thanks for the help. – skelto Jun 21 '16 at 14:28
  • What are your php.ini settings for `upload_max_filesize` and `post_max_size`? You can try to increase them, if they are not high enough – Oleg Jun 21 '16 at 14:47
  • @Curious I increased `upload_max_filesize` to 1000M and `post_max_size` is set to 128M. – skelto Jun 21 '16 at 14:53
  • @Curious I am now getting Error 0 but still nothing has been uploaded. – skelto Jun 21 '16 at 14:56
  • I would also check the folder where the temporary files get stored. This [answer](http://stackoverflow.com/a/16091596/1022914) provides additional information. – Mikey Jun 21 '16 at 15:12

1 Answers1

1

Using the following code, I was able to upload the .obj file.

I had to increase my maximum upload size for it to work.

You may also think of increasing your maximum execution time as commented below, but I didn't have to.

For simplicity, I put everything in one file called form.php.

form.php

<?php
// good idea to turn on errors during development
error_reporting(E_ALL);
ini_set('display_errors', 1);

// ini_set('max_execution_time', 300);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    echo "<br/><b>File Name:</b> " . $_FILES["file"]["name"] . "<br>";
    echo "<b>Type:</b> " . $_FILES["file"]["type"] . "<br>";
    echo "<b>Size:</b> " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
    echo "<b>Temp file:</b> " . $_FILES["file"]["tmp_name"] . "<br>";
    echo "<b>Error:</b> " . $_FILES["file"]["error"] . "<br>";

    $sourcePath = $_FILES['file']['tmp_name'];          // Storing source path of the file in a variable
    $targetPath = "uploads/" . $_FILES['file']['name'];    // Target path where file is to be stored
    if (move_uploaded_file($sourcePath, $targetPath)) { // Moving Uploaded file
        echo "<span id='success'>Image Uploaded Successfully...!!</span><br/>";
    } else {
        echo "<span id='success'>Image was not Uploaded</span><br/>";
    }
    exit;
}
?>

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
</head>
<body>
    <form action="form.php" method="post" enctype="multipart/form-data">
        <label>File</label>
        <input type="file" name="file">
        <input type="submit" value="Upload"> 
    </form>
    <div></div>
</body>
<script>
$(function () {
    $('form').on('submit', function (e) {
        e.preventDefault();
        // logic
        $.ajax({
            url: this.action,
            type: this.method,
            data: new FormData(this), // important
            processData: false, // important
            contentType: false, // important
            success: function (res) {
                $('div').html(res);
            }
        });
    });
});
</script>
</html>

So, first test to see if you can upload the .obj file using the code above.

As you are testing it out, have your browser's developer tool open. Monitor your Network/XHR tab [Chrome, Firefox] to see the request that gets made when you click Upload.

If it works, try using the same logic in your original code.

var formData = new FormData();
formData.append('file', result);   

$.ajax({
    url: "ExecuteMaya.php",
    type: "post",
    data: formData, // important
    processData: false, // important
    contentType: false, // important!
    success: function (res) {
        console.log(res);
    }
});

Again, monitor the request made in your Network/XHR tab and look at what is being sent.

Community
  • 1
  • 1
Mikey
  • 6,728
  • 4
  • 22
  • 45
  • Thanks for all the help! This makes things a lot clearer. I'm getting this (https://justpaste.it/vh9z) printed on the next screen whenever I upload the .OBJ file. – skelto Jun 21 '16 at 09:45
  • I think that I was getting the above errors as I integrated your code into my separate HTML and PHP files. I have now tried what you have stated in your answer, by creating a form.php file and putting all of the code in there. However it still says the 'Image was not Uploaded'. Here is an image of what is being shown (https://postimg.org/image/e4sxtmblj/). – skelto Jun 21 '16 at 11:38
  • I'm not sure if this is of any use, but here is the result of var_dump($_FILES): **array(1) { ["file"]=> array(5) { ["name"]=> string(16) "CharacterOBJ.obj" ["type"]=> string(0) "" ["tmp_name"]=> string(0) "" ["error"]=> int(1) ["size"]=> int(0) } }** – skelto Jun 21 '16 at 13:25
  • Notice how it says `["error"]=> int(1)` that means the `$_FILES['file']['error']`' is 1 i.e. [UPLOAD_ERR_INI_SIZE](http://php.net/manual/en/features.file-upload.errors.php) which means your file is too big. – Mikey Jun 21 '16 at 13:49
  • I changed the max upload size (made it huge just in case) and restarted AMPPS but I am still getting the same error. Here is the new upload size **upload_max_filesize = 100000000000000000M** – skelto Jun 21 '16 at 13:54
  • I've even tried a small TXT file that contains the word 'Test' and it still does not upload. – skelto Jun 21 '16 at 13:59
  • Add `enctype="multipart/form-data"` to the form tag (as edited above). Comment out all the JavaScript and see if you can upload files without using AJAX. If it doesn't work, then you have a basic uploading problem. I would suggest you read [this](http://php.net/manual/en/features.file-upload.common-pitfalls.php) and then ask a new question if there are still problems. Because I just ran this code with (and without JavaScript) and I can upload files. And I hope you placed an `uploads` folder with the right permissions within the same folder as `form.php`. – Mikey Jun 21 '16 at 14:20
  • This 'PHP: Common Pitfalls' document you have linked me talks about a 'MAX_FILE_SIZE' which I cannot find in my php.ini file. Would this be located elsewhere? I have checked 'post_max_size' which is set to 128M, so there shouldn't be any problems with this variable at least. I commented out the JavaScript like you said and it still did not upload, so I guess I have an uploading problem. Thanks for all the help. – skelto Jun 21 '16 at 14:51
  • I've now been able to send the small TXT file, I discovered that I had two form.php files. I still get an Error 1 when sending the .OBJ even though I've altered the upload sizes and restarted the server. – skelto Jun 21 '16 at 15:42
  • 1
    I must have been updated the wrong php.ini file. I went to the directory for the php.ini file stated on the php.info() page and changed the `upload_max_filesize` there and I was then able to send the .OBJ file. Thanks for the help! – skelto Jun 22 '16 at 11:13