Sending json with files nested in lists with ajax - javascript

I am developping a form with some basic inputs and a mini form (in a popup) with a list of foos and each foo have its own attachement file
{
// form fields
...
foos: [
{
// foo form fields
...
attachment: { /* File type */ }
},
...
]
}
before i add the attachement property (file upload), everything work good when i submit the whole form with axios to the backend api server (i am using redux-form to manage the form state)
I use JSON.stringify(formValues) to send data with axios as json
But when i add the attachement property i don't know how to send the form because i read that with the file involved in the form i can't no longer send the form as json but I have to use FormData
The problem is I have nested file objects within a list so how can i send the whole form ?

I achieved the same as this.
let formData = new FormData();
formData.append("file", file);
//here my formData is in JSON format
formData.append("formData", JSON.stringify(formData));
const config = {
method: "POST", //change according to your API
data: formData,
url: api, //API Url
headers: {
"Content-Type": "multipart/form-data",
}
};
axios
.request(config)
.then(function(response) {
console.log(response.data);
}
})
.catch(error => {
console.log(error);
});

Declare a state variable Images which is an array type.
On change of file input assign files to Images array (handleOptionImages()).
Append this Images array in the formData object along with other form data.
Finally, send the formData object in your axios request.
<form>
<input type="file" onChange={e =>this.handleOptionImages(e)}>
<input type="file" onChange={e =>this.handleOptionImages(e)}>
<input type="text" name="user" value={this.state.value} onChange={e=>this.handleChange(e)}>
<button onClick={e=>submitForm(e)}>submit</button>
</form>
define a constructor with blank state like
constructor(props) {
super(props);
this.state = {
user:"",
Images:[]
}
}
handleChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
handleOptionImages(e) {
let Images = this.state.Images.slice();
let media = e.target.files[0];
Images[] = media; // Update it with the modified email.
this.setState({ Images: Images });
}
submitForm(e){
let formdata = new FormData();
formdata.append("user",this.state.user);
if (this.state.Images) {
for (const file of this.state.Images) {
formdata.append("Images[]", file);
}
}
// add your axios code
axios.post("your api path", formdata)
.then(res => {
//handle success
} else {
// handle error
}
});
}
Please have a look I hope it will help you.
Thanks

To set a content-type you need to pass a file-like object. You can create one using a Blob.
const obj = {
hello: "world"
};
const json = JSON.stringify(obj);
const blob = new Blob([json], {
type: 'application/json'
});
const data = new FormData();
data.append("document", blob);
axios({
method: 'post',
url: '/sample',
data: data,
})
jQuery + Ajax for more details refer link
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
});

Related

appand formData and state values into single array and pass throgh axios

I am trying to pass values in allvalues and formData into a single array and pass it through axios.
Here is my code:
constructor(props) {
super(props);
this.state = {
allValues: {
name: "",
class: "",
school: ""
},
}
}
let formData = new FormData();
axios
.post(
'url',
formData, //appand formdata and allValues
{
headers: {
Authorization: `token ` + localStorage.getItem('token'),
'Content-type': 'multipart/form-data',
},
}
)
.then((res) => {
console.log(`Success` + res.data);
});
In order to pass a complex object structure or an array of some sort through, you need to jsonify your data.
Here is how you can pass allValues in your request:
formData.append("allValues", JSON.stringify(this.state.allValues))
Keep in mind that you will need to convert the json back to whatever it is you need on your backend (for example, in node it would convert back to a JS object, in python it would convert to a dictionary etc)

AttributeError: 'NoneType' object has no attribute 'decode' when sending a form through JS

I'm trying to send some data through a form using JavaScript Fetch to a Django view, including an image. I keep getting this error message nine times as if no data was sent to the back end:
My view is as follows:
if "contributors" in data:
try:
Project.objects.get(title=data['title'])
return JsonResponse({'error': 'Project title already exists!'}, status=406)
except Project.DoesNotExist:
form = ProjectForm(request.POST, request.FILES)
project = Project.objects.create(
title=data['title'],
description=data['description'], logo=data['logo'])
return JsonResponse({"message": "Project successfully created!"}, status=201)
and my JavaScript:
const projectName = document.getElementById("project_name");
const contributors = document.getElementById("id_contributors");
const description = document.getElementById("id_description");
const logo = document.getElementById("id_logo");
const projectCsrf = document.getElementsByName("csrfmiddlewaretoken")[0];
document.getElementById("submitProjectForm").addEventListener("click", () => {
let formData = {
title: projectName.value,
contributors: contributors.value,
description: description.value,
logo: logo.files[0],
};
submitForm(projectCsrf, formData);
});
function submitForm(csrf, fields) {
const request = new Request(window.location.origin, {
headers: {
"X-CSRFToken": csrf.value,
"Content-Type": "multipart/form-data",
},
});
fetch(request, {
method: "POST",
body: JSON.stringify(fields),
})
.then((response) => response.json())
.then((result) => alert(result.message ? result.message : result.error))
.catch((err) => console.log(err));
}
is it maybe due to python's Json.loads method not being able to decode the JavaScript File object? Thanks in advance!
As you are including an image in your data and your data is a formdata why you are converting it to a string:
fetch(request, {
method: "POST",
body: JSON.stringify(fields),
})
I think you should add formdata itself to body of fetch api
fetch(request, {
method: "POST",
body: fields,
})
So after hours of debugging I managed to figure it out. Ali javanmardi was partially right in that i should not have been converting the data to JSON because I was sending files.
The main issue for this error was in my headers in my fetch function:
"Content-Type": "multipart/form-data",
This appeared to be causing the main issue, when I changed this to:
"X-Requested-With": "XMLHttpRequest"
it worked.
I also converted all of the data collected from the form into FormData, rather than creating my own object:
let formData = new FormData();
formData.append("logo", logo.files[0]);
formData.append("title", projectName.value);
formData.append("contributors", contributors.value);
formData.append("description", description.value);
On the back end in my view, I should have been saving the form instance instead of creating a new Project object:
new_form = ProjectForm(request.POST, request.FILES)
if new_form.is_valid():
new_form.save()
Now I can upload images fine.

How to upload images in vue js without base64 format?

When I do this way I am getting base64 encoded image. I need to just upload the file. How can I change the code
<script>
submitBox = new Vue({
el: "#submitBox",
data: {
username: '',
category: '',
subcategory: [],
image: '',
},
methods: {
onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage(file) {
var image = new Image();
var reader = new FileReader();
var vm = this;
reader.onload = (e) => {
vm.image = e.target.result;
};
reader.readAsDataURL(file);
},
handelSubmit: function(e) {
var vm = this;
data = {};
data['username'] = this.username;
data['category'] = this.category;
data['subcategory'] = this.subcategory;
data['image'] = this.image;
$.ajax({
url: 'http://127.0.0.1:8000/api/add/post/',
data: data,
type: "POST",
dataType: 'json',
success: function(e) {
if (e.status) {
alert("Registration Success")
window.location.href = "https://localhost/n2s/registersuccess.html";
} else {
vm.response = e;
alert("Registration Failed")
}
}
});
return false;
}
},
});
</script>
My html code is
<div id="submitBox">
<form method="POST" onSubmit="return false;" data-parsley-validate="true" v-on:submit="handelSubmit($event);">
<input name="username" type="text" class="form-control" id="name" placeholder="Name" required="required" v-model="username" data-parsley-minlength="4"/>
<select title="Select" v-model="category" name="category" ref="category">
<option v-for="post in articles" v-bind:value="post.name" >{{post.name}}</option>
</select>
<input class="form-control" type="file" id="property-images" #change="onFileChange">
</form>
</div>
How can I able to upload images without base64 encoding? When I am doing this way I am only able to upload image in base64 format. I need just file upload?
Remove onSubmit attribute (that should really be spelled onsubmit (lowercased)
Use vues owns event modifiers v-on:submit.prevent="handelSubmit"
Remove return false; in handelSubmit function
You are say "images" like it means plural?
So maybe you wanna add the multiple attribute to the file input?
<input type="file" multiple>
To me this all really seems like you want to turn a post request of a from into a ajax request. All the information is already in the form so you could just easily use the FormData constructor and select the form element. You just need to set the name attribute to the file input as well.
<input type="file" name="image" multiple>
But I don't see the subcategory which you might need to add manually.
So here is what i would have done:
handelSubmit(e) {
var form = e.target; // Get hold of the form element from the event
var fd = new FormData(form); // create a FormData
// Add the subcategory
fd.append('subcategory', this.subcategory.join(', '));
// or do this to get more of a array like:
// (depends upon server logic)
//
// this.subcategory.forEach(function(category){
// fd.append('subcategory', category);
// })
// to inspect what the formdata contains
// better to remove in production
// spread operator isn't cross browser compitable
console.log(...fd);
$.ajax({
url: 'http://127.0.0.1:8000/api/add/post/',
data: fd, // data is a FormData instance
type: "POST",
processData: false, // stop jQuery's transformation
contentType: false, // stop jQuery's from setting wrong content-type header
success(e) {
if (e.status) {
alert("Registration Success")
window.location.href = "https://localhost/n2s/registersuccess.html";
} else {
vm.response = e;
alert("Registration Failed")
}
}
});
// For persornal reason i don't like how
// jQuery are unhandel to accept a FormData
//
// So here are some insporation if you can use the new fetch instead
/*
fetch('http://127.0.0.1:8000/api/add/post/', {method: 'post', body: fd})
.then(function(res){
// Here you have only recived the headers
console.log(res.ok) // true for 2xx responses, false otherwise
return res.text() // or .json()
})
.then(function(text){
// Here you have recived the hole response
console.log(text)
})
*/
}
I fail to see the reason why you would need the createImage and the onFileChange functions.
The thing you also have to notices is that when using jQuery's ajax and and Formdata is that you need to set both contentType and processData to false otherwise jQuery will do incorrect things to the request
This will change the post from a json payload to a multipart payload which is the best choice for uploading files... you save more bandwidth and need to do less on the server

XMLHTTPREQUEST send file and parameters [duplicate]

I'm using jQuery and Ajax for my forms to submit data and files but I'm not sure how to send both data and files in one form?
I currently do almost the same with both methods but the way in which the data is gathered into an array is different, the data uses .serialize(); but the files use = new FormData($(this)[0]);
Is it possible to combine both methods to be able to upload files and data in one form through Ajax?
Data jQuery, Ajax and html
$("form#data").submit(function(){
var formData = $(this).serialize();
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
<form id="data" method="post">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<button>Submit</button>
</form>
Files jQuery, Ajax and html
$("form#files").submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
<form id="files" method="post" enctype="multipart/form-data">
<input name="image" type="file" />
<button>Submit</button>
</form>
How can I combine the above so that I can send data and files in one form via Ajax?
My aim is to be able to send all of this form in one post with Ajax, is it possible?
<form id="datafiles" method="post" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button>Submit</button>
</form>
The problem I had was using the wrong jQuery identifier.
You can upload data and files with one form using ajax.
PHP + HTML
<?php
print_r($_POST);
print_r($_FILES);
?>
<form id="data" method="post" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button>Submit</button>
</form>
jQuery + Ajax
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
});
Short Version
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.post($(this).attr("action"), formData, function(data) {
alert(data);
});
});
another option is to use an iframe and set the form's target to it.
you may try this (it uses jQuery):
function ajax_form($form, on_complete)
{
var iframe;
if (!$form.attr('target'))
{
//create a unique iframe for the form
iframe = $("<iframe></iframe>").attr('name', 'ajax_form_' + Math.floor(Math.random() * 999999)).hide().appendTo($('body'));
$form.attr('target', iframe.attr('name'));
}
if (on_complete)
{
iframe = iframe || $('iframe[name="' + $form.attr('target') + '"]');
iframe.load(function ()
{
//get the server response
var response = iframe.contents().find('body').text();
on_complete(response);
});
}
}
it works well with all browsers, you don't need to serialize or prepare the data.
one down side is that you can't monitor the progress.
also, at least for chrome, the request will not appear in the "xhr" tab of the developer tools but under "doc"
I was having this same issue in ASP.Net MVC with HttpPostedFilebase and instead of using form on Submit I needed to use button on click where I needed to do some stuff and then if all OK the submit form so here is how I got it working
$(".submitbtn").on("click", function(e) {
var form = $("#Form");
// you can't pass Jquery form it has to be javascript form object
var formData = new FormData(form[0]);
//if you only need to upload files then
//Grab the File upload control and append each file manually to FormData
//var files = form.find("#fileupload")[0].files;
//$.each(files, function() {
// var file = $(this);
// formData.append(file[0].name, file[0]);
//});
if ($(form).valid()) {
$.ajax({
type: "POST",
url: $(form).prop("action"),
//dataType: 'json', //not sure but works for me without this
data: formData,
contentType: false, //this is requireded please see answers above
processData: false, //this is requireded please see answers above
//cache: false, //not sure but works for me without this
error : ErrorHandler,
success : successHandler
});
}
});
this will than correctly populate your MVC model, please make sure in your Model, The Property for HttpPostedFileBase[] has the same name as the Name of the input control in html i.e.
<input id="fileupload" type="file" name="UploadedFiles" multiple>
public class MyViewModel
{
public HttpPostedFileBase[] UploadedFiles { get; set; }
}
Or shorter:
$("form#data").submit(function() {
var formData = new FormData(this);
$.post($(this).attr("action"), formData, function() {
// success
});
return false;
});
EDIT: with the new version of JQuery (3.6), you could also try using contentType function argument instead of enctype. Try contentType: multipart/form-data.
For me, it didn't work without enctype: 'multipart/form-data' field in the Ajax request. I hope it helps someone who is stuck in a similar problem.
Even though the enctype was already set in the form attribute, for some reason, the Ajax request didn't automatically identify the enctype without explicit declaration (jQuery 3.3.1).
// Tested, this works for me (jQuery 3.3.1)
fileUploadForm.submit(function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: $(this).attr('action'),
enctype: 'multipart/form-data',
data: new FormData(this),
processData: false,
contentType: false,
success: function (data) {
console.log('Thank God it worked!');
}
}
);
});
// enctype field was set in the form but Ajax request didn't set it by default.
<form action="process/file-upload" enctype="multipart/form-data" method="post" >
<input type="file" name="input-file" accept="text/plain" required>
...
</form>
As others mentioned above, please also pay special attention to the contentType and processData fields.
A Simple but more effective way:
new FormData() is itself like a container (or a bag). You can put everything attr or file in itself.
The only thing you'll need to append the attribute, file, fileName eg:
let formData = new FormData()
formData.append('input', input.files[0], input.files[0].name)
and just pass it in AJAX request. Eg:
let formData = new FormData()
var d = $('#fileid')[0].files[0]
formData.append('fileid', d);
formData.append('inputname', value);
$.ajax({
url: '/yourroute',
method: 'POST',
contentType: false,
processData: false,
data: formData,
success: function(res){
console.log('successfully')
},
error: function(){
console.log('error')
}
})
You can append n number of files or data with FormData.
and if you're making AJAX Request from Script.js file to Route file in Node.js beware of using
req.body to access data (ie text)
req.files to access file (ie image, video etc)
The code below works for me
$(function () {
debugger;
document.getElementById("FormId").addEventListener("submit", function (e) {
debugger;
if (ValidDateFrom()) { // Check Validation
var form = e.target;
if (form.getAttribute("enctype") === "multipart/form-data") {
debugger;
if (form.dataset.ajax) {
e.preventDefault();
e.stopImmediatePropagation();
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action);
xhr.onreadystatechange = function (result) {
debugger;
if (xhr.readyState == 4 && xhr.status == 200) {
debugger;
var responseData = JSON.parse(xhr.responseText);
SuccessMethod(responseData); // Redirect to your Success method
}
};
xhr.send(new FormData(form));
}
}
}
}, true);
});
In your Action Post Method, pass parameter as HttpPostedFileBase UploadFile and make sure your file input has same as mentioned in your parameter of the Action Method.
It should work with AJAX Begin form as well.
Remember over here that your AJAX BEGIN Form will not work over here since you make your post call defined in the code mentioned above and you can reference your method in the code as per the Requirement
I know I am answering late but this is what worked for me
Just to remind, in 2022 you don't need to use jquery. Try js standard Fetch API
var formData = new FormData(this);
fetch(url, {
method: 'POST',
body: formData
})
.then(response => {
if(response.ok) {
//success
alert(response);
} else {
throw Error('Server error');
}
})
.catch(error => {
console.log('fail', error);
});
This is a solution that I implemented
var formData = new FormData();
var files = $('input[type=file]');
for (var i = 0; i < files.length; i++) {
if (files[i].value == "" || files[i].value == null) {
return false;
}
else {
formData.append(files[i].name, files[i].files[0]);
}
}
var formSerializeArray = $("#Form").serializeArray();
for (var i = 0; i < formSerializeArray.length; i++) {
formData.append(formSerializeArray[i].name, formSerializeArray[i].value)
}
$.ajax({
type: 'POST',
data: formData,
contentType: false,
processData: false,
cache: false,
url: '/Controller/Action',
success: function (response) {
if (response.Success == true) {
return true;
}
else {
return false;
}
},
error: function () {
return false;
},
failure: function () {
return false;
}
});
---Solution for DOT NET CORE MVC Implementation---
While looking at this question I though I should right .NET CORE implementation for this because the question is not specific to any backend language.
So guys here is the standalone implementation example.
Objective :- To submit form fields including files and how we can get data in a single model at backend
HTML Code / View Code - Views/Home/Index.cshtml
#{
ViewData["Title"] = "Home Page";
}
<input type="file" id="FileUpload1" multiple />
<div>
<label>Enter First Name :</label>
<input type="text" id="nameText" maxlength="50" />
</div>
<input type="button" id="btnUpload" value="Submit Form with Files" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function () {
$('#btnUpload').click(function () {
// Checking whether FormData is available in browser
if (window.FormData !== undefined) {
var fileUpload = $("#FileUpload1").get(0);
var files = fileUpload.files;
// Create FormData object
var fileData = new FormData();
// Looping over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append("files", files[i]);
}
// Adding one more key to FormData object
fileData.append('FirstName', $("#nameText").val());
$.ajax({
url: '/Home/UploadFiles',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fileData,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
} else {
alert("FormData is not supported.");
}
});
});
</script>
Backend Code / Controller action method Controllers/HomeController.cs
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IWebHostEnvironment _environment;
public HomeController(ILogger<HomeController> logger, IWebHostEnvironment environment)
{
_logger = logger;
_environment = environment;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[HttpPost]
public async Task<IActionResult> UploadFiles(MyForm myForm)
{
var files = myForm.Files;
// First Name
string name = myForm.FirstName;
// check All files
foreach (IFormFile source in files)
{
string filename = ContentDispositionHeaderValue.Parse(source.ContentDisposition).FileName.Trim('"');
filename = this.EnsureCorrectFilename(filename);
string fileWithPath = this.GetPathAndFilename(filename);
// Create directory if not exist
Directory.CreateDirectory(Path.GetDirectoryName(fileWithPath));
using (FileStream output = System.IO.File.Create(fileWithPath))
await source.CopyToAsync(output);
}
return Ok("Success");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
public class MyForm
{
public string FirstName { get; set; }
public IList<IFormFile> Files { get; set; }
}
private string EnsureCorrectFilename(string filename)
{
if (filename.Contains("\\"))
filename = filename.Substring(filename.LastIndexOf("\\") + 1);
return filename;
}
private string GetPathAndFilename(string filename)
{
return Path.Combine(_environment.ContentRootPath, "uploadedFiles", filename);
}
}
Full Source Code Repo: https://github.com/rj-learning/DotNetCoreFileUpload
In my case I had to make a POST request, which had information sent through the header, and also a file sent using a FormData object.
I made it work using a combination of some of the answers here, so basically what ended up working was having this five lines in my Ajax request:
contentType: "application/octet-stream",
enctype: 'multipart/form-data',
contentType: false,
processData: false,
data: formData,
Where formData was a variable created like this:
var file = document.getElementById('uploadedFile').files[0];
var form = $('form')[0];
var formData = new FormData(form);
formData.append("File", file);
you can just append them on your formdata, add your files and datas in it.you can read this..
https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
for better understanding. you can separately retrieve them $_FILES for your files and $_POST for your data.
<form id="form" method="post" action="otherpage.php" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button type='button' id='submit_btn'>Submit</button>
</form>
<script>
$(document).on("click", "#submit_btn", function (e) {
//Prevent Instant Click
e.preventDefault();
// Create an FormData object
var formData = $("#form").submit(function (e) {
return;
});
//formData[0] contain form data only
// You can directly make object via using form id but it require all ajax operation inside $("form").submit(<!-- Ajax Here -->)
var formData = new FormData(formData[0]);
$.ajax({
url: $('#form').attr('action'),
type: 'POST',
data: formData,
success: function (response) {
console.log(response);
},
contentType: false,
processData: false,
cache: false
});
return false;
});
</script>
///// otherpage.php
<?php
print_r($_FILES);
?>

File Upload without Form

Without using any forms whatsoever, can I just send a file/files from <input type="file"> to 'upload.php' using POST method using jQuery. The input tag is not inside any form tag. It stands individually. So I don't want to use jQuery plugins like 'ajaxForm' or 'ajaxSubmit'.
You can use FormData to submit your data by a POST request. Here is a simple example:
var myFormData = new FormData();
myFormData.append('pictureFile', pictureInput.files[0]);
$.ajax({
url: 'upload.php',
type: 'POST',
processData: false, // important
contentType: false, // important
dataType : 'json',
data: myFormData
});
You don't have to use a form to make an ajax request, as long as you know your request setting (like url, method and parameters data).
All answers here are still using the FormData API. It is like a "multipart/form-data" upload without a form. You can also upload the file directly as content inside the body of the POST request using xmlHttpRequest like this:
var xmlHttpRequest = new XMLHttpRequest();
var file = ...file handle...
var fileName = ...file name...
var target = ...target...
var mimeType = ...mime type...
xmlHttpRequest.open('POST', target, true);
xmlHttpRequest.setRequestHeader('Content-Type', mimeType);
xmlHttpRequest.setRequestHeader('Content-Disposition', 'attachment; filename="' + fileName + '"');
xmlHttpRequest.send(file);
Content-Type and Content-Disposition headers are used for explaining what we are sending (mime-type and file name).
I posted similar answer also here.
UPDATE (January 2023):
You can also use the Fetch API to upload a file directly as binary content (as also was suggested in the comments).
const file = ...file handle...
const fileName = ...file name...
const target = ...target...
const mimeType = ...mime type...
const promise = fetch(target, {
method: 'POST',
body: file,
headers: {
'Content-Type': mimeType,
'Content-Disposition', `attachment; filename="${fileName}"`,
},
},
});
promise.then(
(response) => { /*...do something with response*/ },
(error) => { /*...handle error*/ },
);
See also a related question here: https://stackoverflow.com/a/48568899/1697459
Step 1: Create HTML Page where to place the HTML Code.
Step 2: In the HTML Code Page Bottom(footer)Create Javascript: and put Jquery Code in Script tag.
Step 3: Create PHP File and php code copy past. after Jquery Code in $.ajax Code url apply which one on your php file name.
JS
//$(document).on("change", "#avatar", function() { // If you want to upload without a submit button
$(document).on("click", "#upload", function() {
var file_data = $("#avatar").prop("files")[0]; // Getting the properties of file from file field
var form_data = new FormData(); // Creating object of FormData class
form_data.append("file", file_data) // Appending parameter named file with properties of file_field to form_data
form_data.append("user_id", 123) // Adding extra parameters to form_data
$.ajax({
url: "/upload_avatar", // Upload Script
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: form_data, // Setting the data attribute of ajax with file_data
type: 'post',
success: function(data) {
// Do something after Ajax completes
}
});
});
HTML
<input id="avatar" type="file" name="avatar" />
<button id="upload" value="Upload" />
Php
print_r($_FILES);
print_r($_POST);
Basing on this tutorial, here a very basic way to do that:
$('your_trigger_element_selector').on('click', function(){
var data = new FormData();
data.append('input_file_name', $('your_file_input_selector').prop('files')[0]);
// append other variables to data if you want: data.append('field_name_x', field_value_x);
$.ajax({
type: 'POST',
processData: false, // important
contentType: false, // important
data: data,
url: your_ajax_path,
dataType : 'json',
// in PHP you can call and process file in the same way as if it was submitted from a form:
// $_FILES['input_file_name']
success: function(jsonData){
...
}
...
});
});
Don't forget to add proper error handling
Try this puglin simpleUpload, no need form
Html:
<input type="file" name="arquivo" id="simpleUpload" multiple >
<button type="button" id="enviar">Enviar</button>
Javascript:
$('#simpleUpload').simpleUpload({
url: 'upload.php',
trigger: '#enviar',
success: function(data){
alert('Envio com sucesso');
}
});
A non-jquery (React) version:
JS:
function fileInputUpload(e){
let formData = new FormData();
formData.append(e.target.name, e.target.files[0]);
let response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
let result = await response.json();
console.log(result.message);
}
HTML/JSX:
<input type='file' name='fileInput' onChange={(e) => this.fileInput(e)} />
You might not want to use onChange, but you can attach the uploading part to any another function.
Sorry for being that guy but AngularJS offers a simple and elegant solution.
Here is the code I use:
ngApp.controller('ngController', ['$upload',
function($upload) {
$scope.Upload = function($files, index) {
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
$scope.upload = $upload.upload({
file: file,
url: '/File/Upload',
data: {
id: 1 //some data you want to send along with the file,
name: 'ABC' //some data you want to send along with the file,
},
}).progress(function(evt) {
}).success(function(data, status, headers, config) {
alert('Upload done');
}
})
.error(function(message) {
alert('Upload failed');
});
}
};
}]);
.Hidden {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-controller="ngController">
<input type="button" value="Browse" onclick="$(this).next().click();" />
<input type="file" ng-file-select="Upload($files, 1)" class="Hidden" />
</div>
On the server side I have an MVC controller with an action the saves the files uploaded found in the Request.Files collection and returning a JsonResult.
If you use AngularJS try this out, if you don't... sorry mate :-)

Categories

Resources