Jump to content

XMLHttpRequest Post FormData

SoftwareNinja

Hi there,

 

I am working on a project that requires files been uploaded to an S3 server and I ran into a problem with the Post request.

 

My upload script works perfectly using the following AJax code:

    var form = new FormData();
    let msg = $("#msg").val();

    form.append('file', file);
    form.append('msg', msg);
    form.append('size', file.size);

    $.ajax({
        url: 'upload.php', // point to server-side PHP script 
        dataType: 'text',  // what to expect back from the PHP script, if anything
        cache: false,
        contentType: false,
        processData: false,
        data: form,              
        type: 'post',
        success: function(php_script_response){
            alert(php_script_response); // display response from the PHP script, if any
        }
     });

However this is not the code I want to use as I have a progress bar linked to my other method that I want to use.

 

Here is the code I am trying to use, it is calling my upload script but no FormData is been passed through at all.

    var form = new FormData();
    let msg = $("#msg").val();

    form.append('file', file);
    form.append('msg', msg);
    form.append('size', file.size);
    
    $(".uploader__share").addClass("hidden");
    $(".uploader__progress").removeClass("hidden");

    $("#msg").prop("readonly", true);

    const xhr = new XMLHttpRequest();

    xhr.open("POST", 'upload.php', true);
    xhr.upload.addEventListener("progress", e =>
    {
        const percent = e.lengthComputable ? (e.loaded / e.total) * 100 : 0;
        $(".progress-bar").width(percent.toFixed(5) + "%");
    });

    xhr.setRequestHeader("Content-Type", "text/plain");
    xhr.send(form);

 

I've also tried setting the "setRequestHeader" to: 

xhr.setRequestHeader("Content-Type", "multipart/form-data");

But nothing seems to be working.

 

Can someone help me resole this please :)

 

Thanks in advance!

Link to comment
Share on other sites

Link to post
Share on other sites

You can use axios in react like this.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import progress from "progress-stream"; 
import axios from 'axios'; 
 

class App extends Component {

  constructor() {
    super();
    this.state = {
      fileprogress:null, 
    }
    this.submit.bind(this)
  }
  
  submit(event){
    	event.preventDefault()
        axios.request( {
        method: "post", 
        url: "/aaa", // your url here
        data: myData, 
        onUploadProgress: (p) => {
          console.log(p); 
          this.setState({
            fileprogress: p.loaded / p.total
          })
        }
      }).then (data => {
        this.setState({
          fileprogress: 1.0,
        })
      })
  }

  render() {
    return (
      <div className="App">

        <form onSubmit={this.submit}>

          <div className ="file-progress"> 
            <div className = "file-progress-inner" style = {{width:  (this.state.fileprogress && this.state.fileprogress *100 + "%")}}/> 
            <div>
              {this.state.fileprogress && this.state.fileprogress *100 + "%"}
            </div>
          </div> 

          <input type="file" onChange = {(e) => {
              this.setState({file:e.target.files[0]})
          }}/>
          <input type="submit" />
        </form>
      </div>
    );
  }
}

export default App;

If you arent using a front end framework and are working with vanilla javascript, get axios using this CDN

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

On 12/17/2019 at 5:31 AM, ScottDurkin said:

xhr.upload.addEventListener("progress", e =>
    {
        const percent = e.lengthComputable ? (e.loaded / e.total) * 100 : 0;
        $(".progress-bar").width(percent.toFixed(5) + "%");
    });

 

First thing I would do is a sanity check, and just have it output the variables to the console.

// something like...
console.log(e.lengthComputable + " | " + e.loaded + " | " + e.total);

Just to verify that it's working the way you think.

I would also remove the "const" before percent.  Add that back in when you're sure everything else is working.

 

I'm guessing this is where you're problem is though

$(".progress-bar").width(percent.toFixed(5) + "%");

When I saw your code that line immediately caught my eye.  I've run into so many stupid problems dealing with sizes and alignments in HTML, and that looks exactly like the kind of code that would have many slamming my fists on my desk.

 

 

Just remember the rule of thumb for debugging an unknown problem.

  1. Undo your most recent modifications until you have the code in a working state.
  2. Add your changes back in one at a time until it breaks.
  3. Voila, you've found the problem.

 

EDIT:  Sorry, forgot to add this as well.  Comment out the event listener code for now, and make sure everything about the upload code works (again, see debugging code above).

 

 

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×