I am trying to implement ajax file upload via the HTML5 File API. It's based on Afzaal Ahmad Zeeshan's answer to this question.
I've basically copied the entire code that he wrote, but can't get it to work.
The main aim here is to be able to upload .xls and .xlsx files to the server to work with them later with PHPExcel.
Here's my HTML:
<form class="form-uploadXLS" method="post" action="php/uploadXLS.php" enctype="multipart/form-data">
<div class="form-group">
<div class="col-md-12">
<input type="file" name="xls" class="xls" />
</div>
</div>
<input type="button" value="Upload" class="btn-uploadXLS" />
</form>
<progress></progress>
And here are the jQuery event handlers, just like in the above mentioned answer:
File input onChange event:
$('.xls').on('change', function () {
var file = this.files[0];
var fileName = file.name;
var fileType = file.type;
var fileSize = file.size;
console.log("file name: " + fileName + ", type: " + fileType + ", size: " + fileSize);
});
Upload button's onClick event:
$('.btn-uploadXLS').on('click', function (event) {
event.preventDefault();
console.log("Upload button clicked");
var formData = new FormData($('.form-uploadXLS')[0]);
$.ajax({
url: 'php/uploadXLS.php', //Server script to process data
type: 'POST',
xhr: function () { // Custom XMLHttpRequest
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { // Check if upload property exists
myXhr.upload.addEventListener('progress', progressHandlingFunction, false); // For handling the progress of the upload
}
return myXhr;
},
//Ajax events
beforeSend: function (stuff) {
console.log("BeforeSend");
console.log(stuff);
},
success: function (data) {
console.log("Success!");
console.log(data);
},
error: function (error) {
console.log("Error!");
console.log(error);
},
// Form data
data: formData,
//Options to tell jQuery not to process data or worry about content-type.
cache: false,
contentType: false,
processData: false
});
});
Edit starts here:
And finally here's my PHP code that prints out the $_FILES array:
if(!empty($_FILES['xls'])) {
echo '<pre>',print_r($_FILES,1),'</pre>';
}
else {
die('POST ÜRES');
}
And here's the result:
Array
(
[xls] => Array
(
[name] =>
[type] =>
[tmp_name] =>
[error] => 4
[size] => 0
)
)
For some reason I can't access the error messages, it only contains the number 4.
What am I doing wrong?
For files you need
$_FILES['xls'] not $_POST
Read Handling file uploads
To get more info just print array
echo '<pre>',print_r($_FILES,1),'</pre>'
Read php - file upload
Ajax File Upload with PHP, HTML5 File API and jQuery
Related
I have a file in my view
<form id="upload" enctype="multipart/form-data">
<input type="file" name="fileUpload" id="fileUpload" size="23" />
</form>
and an ajax request
$.ajax({
url: '<%=Url.Action("JsonSave","Survey") %>',
dataType: 'json',
processData: false,
contentType: "multipart/mixed",
data: {
Id: selectedRow.Id,
Value: 'some date was added by the user here :))'
},
cache: false,
success: function (data) {}
});
but there is no file in the Request.Files. Whats wrong with the ajax request?
Upload files using AJAX in ASP.Net MVC
Things have changed since HTML5
JavaScript
document.getElementById('uploader').onsubmit = function () {
var formdata = new FormData(); //FormData object
var fileInput = document.getElementById('fileInput');
//Iterating through each files selected in fileInput
for (i = 0; i < fileInput.files.length; i++) {
//Appending each file to FormData object
formdata.append(fileInput.files[i].name, fileInput.files[i]);
}
//Creating an XMLHttpRequest and sending
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Home/Upload');
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
}
return false;
}
Controller
public JsonResult Upload()
{
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase file = Request.Files[i]; //Uploaded file
//Use the following properties to get file's name, size and MIMEType
int fileSize = file.ContentLength;
string fileName = file.FileName;
string mimeType = file.ContentType;
System.IO.Stream fileContent = file.InputStream;
//To save file, use SaveAs method
file.SaveAs(Server.MapPath("~/")+ fileName ); //File will be saved in application root
}
return Json("Uploaded " + Request.Files.Count + " files");
}
EDIT : The HTML
<form id="uploader">
<input id="fileInput" type="file" multiple>
<input type="submit" value="Upload file" />
</form>
AJAX file uploads are now possible by passing a FormData object to the data property of the $.ajax request.
As the OP specifically asked for a jQuery implementation, here you go:
<form id="upload" enctype="multipart/form-data" action="#Url.Action("JsonSave", "Survey")" method="POST">
<input type="file" name="fileUpload" id="fileUpload" size="23" /><br />
<button>Upload!</button>
</form>
$('#upload').submit(function(e) {
e.preventDefault(); // stop the standard form submission
$.ajax({
url: this.action,
type: this.method,
data: new FormData(this),
cache: false,
contentType: false,
processData: false,
success: function (data) {
console.log(data.UploadedFileCount + ' file(s) uploaded successfully');
},
error: function(xhr, error, status) {
console.log(error, status);
}
});
});
public JsonResult Survey()
{
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
// save file as required here...
}
return Json(new { UploadedFileCount = Request.Files.Count });
}
More information on FormData at MDN
You can't upload files via ajax, you need to use an iFrame or some other trickery to do a full postback. This is mainly due to security concerns.
Here's a decent write-up including a sample project using SWFUpload and ASP.Net MVC by Steve Sanderson. It's the first thing I read getting this working properly with Asp.Net MVC (I was new to MVC at the time as well), hopefully it's as helpful for you.
I have a sample like this on vuejs version: v2.5.2
<form action="url" method="post" enctype="multipart/form-data">
<div class="col-md-6">
<input type="file" class="image_0" name="FilesFront" ref="FilesFront" />
</div>
<div class="col-md-6">
<input type="file" class="image_1" name="FilesBack" ref="FilesBack" />
</div>
</form>
<script>
Vue.component('v-bl-document', {
template: '#document-item-template',
props: ['doc'],
data: function () {
return {
document: this.doc
};
},
methods: {
submit: function () {
event.preventDefault();
var data = new FormData();
var _doc = this.document;
Object.keys(_doc).forEach(function (key) {
data.append(key, _doc[key]);
});
var _refs = this.$refs;
Object.keys(_refs).forEach(function (key) {
data.append(key, _refs[key].files[0]);
});
debugger;
$.ajax({
type: "POST",
data: data,
url: url,
cache: false,
contentType: false,
processData: false,
success: function (result) {
//do something
},
});
}
}
});
</script>
If you posting form using ajax then you can not
send image using $.ajax method,
you have to use classic xmlHttpobject method for saving image,
other alternative of it use submit type instead of button
I have a file in my view
<form id="upload" enctype="multipart/form-data">
<input type="file" name="fileUpload" id="fileUpload" size="23" />
</form>
and an ajax request
$.ajax({
url: '<%=Url.Action("JsonSave","Survey") %>',
dataType: 'json',
processData: false,
contentType: "multipart/mixed",
data: {
Id: selectedRow.Id,
Value: 'some date was added by the user here :))'
},
cache: false,
success: function (data) {}
});
but there is no file in the Request.Files. Whats wrong with the ajax request?
Upload files using AJAX in ASP.Net MVC
Things have changed since HTML5
JavaScript
document.getElementById('uploader').onsubmit = function () {
var formdata = new FormData(); //FormData object
var fileInput = document.getElementById('fileInput');
//Iterating through each files selected in fileInput
for (i = 0; i < fileInput.files.length; i++) {
//Appending each file to FormData object
formdata.append(fileInput.files[i].name, fileInput.files[i]);
}
//Creating an XMLHttpRequest and sending
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Home/Upload');
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
}
return false;
}
Controller
public JsonResult Upload()
{
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase file = Request.Files[i]; //Uploaded file
//Use the following properties to get file's name, size and MIMEType
int fileSize = file.ContentLength;
string fileName = file.FileName;
string mimeType = file.ContentType;
System.IO.Stream fileContent = file.InputStream;
//To save file, use SaveAs method
file.SaveAs(Server.MapPath("~/")+ fileName ); //File will be saved in application root
}
return Json("Uploaded " + Request.Files.Count + " files");
}
EDIT : The HTML
<form id="uploader">
<input id="fileInput" type="file" multiple>
<input type="submit" value="Upload file" />
</form>
AJAX file uploads are now possible by passing a FormData object to the data property of the $.ajax request.
As the OP specifically asked for a jQuery implementation, here you go:
<form id="upload" enctype="multipart/form-data" action="#Url.Action("JsonSave", "Survey")" method="POST">
<input type="file" name="fileUpload" id="fileUpload" size="23" /><br />
<button>Upload!</button>
</form>
$('#upload').submit(function(e) {
e.preventDefault(); // stop the standard form submission
$.ajax({
url: this.action,
type: this.method,
data: new FormData(this),
cache: false,
contentType: false,
processData: false,
success: function (data) {
console.log(data.UploadedFileCount + ' file(s) uploaded successfully');
},
error: function(xhr, error, status) {
console.log(error, status);
}
});
});
public JsonResult Survey()
{
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
// save file as required here...
}
return Json(new { UploadedFileCount = Request.Files.Count });
}
More information on FormData at MDN
You can't upload files via ajax, you need to use an iFrame or some other trickery to do a full postback. This is mainly due to security concerns.
Here's a decent write-up including a sample project using SWFUpload and ASP.Net MVC by Steve Sanderson. It's the first thing I read getting this working properly with Asp.Net MVC (I was new to MVC at the time as well), hopefully it's as helpful for you.
I have a sample like this on vuejs version: v2.5.2
<form action="url" method="post" enctype="multipart/form-data">
<div class="col-md-6">
<input type="file" class="image_0" name="FilesFront" ref="FilesFront" />
</div>
<div class="col-md-6">
<input type="file" class="image_1" name="FilesBack" ref="FilesBack" />
</div>
</form>
<script>
Vue.component('v-bl-document', {
template: '#document-item-template',
props: ['doc'],
data: function () {
return {
document: this.doc
};
},
methods: {
submit: function () {
event.preventDefault();
var data = new FormData();
var _doc = this.document;
Object.keys(_doc).forEach(function (key) {
data.append(key, _doc[key]);
});
var _refs = this.$refs;
Object.keys(_refs).forEach(function (key) {
data.append(key, _refs[key].files[0]);
});
debugger;
$.ajax({
type: "POST",
data: data,
url: url,
cache: false,
contentType: false,
processData: false,
success: function (result) {
//do something
},
});
}
}
});
</script>
If you posting form using ajax then you can not
send image using $.ajax method,
you have to use classic xmlHttpobject method for saving image,
other alternative of it use submit type instead of button
I have a Node/Express app and i want to sent a file with a form, i want to send it with ajax so i can process the server response.
So far my form is:
<form method='POST' enctype='multipart/form-data' id='excelform'>
<input type='file' id='target_file' name='target_file' required>
</form>
<button class='btn btn-menu3 align-self-end' onClick='excel_email9f();'>Enviar</button>
i have a button that calls the following function for an ajax request:
function excel_email9f(){
var data = new FormData();
var file = $('#target_file')[0].files[0];
data.append('file', file);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/Excelemail9f",
data: data,
processData: false,
contentType: false,
cache: false,
timeout: 600000,
success: function (data) {
var response = data.q0;
alert(response);
},
error: function (e) {
console.log("ERROR : ", e);
}
});
};
i can access the file and its properties like name.
On server side i have this route
app.post('/Excelemail9f',function(req,res){
// checking req.files is empty or not
if (Object.keys(req.files).length == 0) {
return res.status(400).send('No files were uploaded.');
}
console.log('name: ' + req.files.target_file.name);
let target_file = req.files.target_file;
// target_file.mv(path, callback)
target_file.mv(path.join(__dirname, 'uploads', target_file.name), (err) => {
if (err) throw err;
res.send(JSON.stringify({q0 : 0}));
})
})
How do i access the file on the server side, i use req.files.target_file but i get the following error:
TypeError: Cannot read property 'name' of undefined
You're posting the data as a FormData object, but you're referring to the HTML input element's ID as the filename. You populate the FormData object by calling data.append('file', file);, so you need to reference it by req.files.file rather than req.files.target_file.
I am currently using this code to select a file from local disk to my api:
<script language="javascript" type="text/javascript">
$(document).ready(function(){
$(':file').on('change', function () {
var file = this.files[0];
if (file.type !== "video/mp4" && file.type!== "video/quicktime") {
alert("Content must be video .mp4 or .mov")
}
$(':button').on('click', function () {
if (file.type == "video/mp4" || file.type == "video/quicktime"){
$.ajax({
// Your server script to process the upload
url: 'azureAPI',
type: 'POST',
// Form data
data: new FormData($('form')[0]),
// Tell jQuery not to process data or worry about content-type
// You *must* include these options!
cache: false,
contentType: false,
processData: false,
// Custom XMLHttpRequest
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
// For handling the progress of the upload
myXhr.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
$('progress').attr({
value: e.loaded,
max: e.total,
});
}
}, false);
}
return myXhr;
}
});
} else {
alert ("File type must be .mp4 or .mov")
}
});
});
});
</script>
This sends (what I am assuming is) binary data in the form of this:
���
1!QAa"q2B���R�#3br��u�����S6C$%��5�cts�T&D4��U��d���e!1AQa2"q�#����3��B���X"��?��!=��W�u�ٗ�-2���?����ۯ�Կ�i���t����M���Y�-��-Vdϊ�P�<�<U#TY]K��dW
���
I am using Azure, and now trying to send this to Microsoft Video Indexer, which says to send the data as multipart/form-data in the body. (see https://api-portal.videoindexer.ai/docs/services/Operations/operations/Upload-Video?)
I tried sending the binary data in the body, but it said it required string/buffer.
I then tried sending the binary data in the body as var body = Buffer.from(req.body,'binary')
Which sent, but VI responded saying that there was an issue indexing the data, perhaps as I sent with the wrong encoding?
To work around this, I am now trying to save that binary data to a block blob first, then I will call that url after, however I am having trouble saving binary data to Azure block blob using:
var buf = Buffer.from(req.body, 'binary');
blobService.createBlockBlobFromText(container, 'fileName.mp4', buf, {contentSettings: {contentType: 'video/mp4', contentEncoding: 'binary'}}, function (error, result, response) {
if(!error){
callback('uploaded');
} else {
callback('nope');
}
});
I tried this, without the contentSettings at first but that saved the data as contentType: application/octet-stream which wasn't opening as a video. I then added contentType, and lasted tried adding contentEncoding as well.
This saved the correct contentType but still the video could not be opened.
Does anyone know how to encode the data correctly to either send in the first instance straight to video indexer, or secondly to save binary data to Azure blob storage?
Thanks for any pointers, apologies if I left anything out.
According to my test, if you want to use Azure function to upload file to Azure blob, please refer to the following code.
front-end
<!DOCTYPE html>
<html>
<script type="text/javascript"
src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.js">
</script>
<body>
<form enctype="multipart/form-data">
<input name="file" type="file" accept="video/*"/>
<input type="button" value="Upload" />
</form>
<progress></progress>
<script language="javascript" type="text/javascript">
$(document).ready(function(){
$(':file').on('change', function () {
var file = this.files[0];
if (file.type !== "video/mp4" && file.type!== "video/quicktime") {
alert("Content must be video .mp4 or .mov")
}
$(':button').on('click', function () {
if (file.type == "video/mp4" || file.type == "video/quicktime"){
$.ajax({
// Your server script to process the upload
url: '',
type: 'POST',
crossDomain: true,
enctype: 'multipart/form-data',
// Form data
data: new FormData($('form')[0]),
// Tell jQuery not to process data or worry about content-type
// You *must* include these options!
cache: false,
contentType: false,
processData: false,
success : function(data){console.log(data);},
// Custom XMLHttpRequest
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
// For handling the progress of the upload
myXhr.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
$('progress').attr({
value: e.loaded,
max: e.total,
});
}
}, false);
}
return myXhr;
}
});
} else {
alert ("File type must be .mp4 or .mov")
}
});
});
});
</script>
</body>
</html>
Azure function
var multipart = require('parse-multipart')
var azure = require('azure-storage');
var getStream = require('into-stream')
module.exports = async function (context, request) {
context.log('JavaScript HTTP trigger function processed a request.');
// encode body to base64 string
var bodyBuffer = Buffer.from(request.body);
var boundary = multipart.getBoundary(request.headers['content-type']);
// parse the body
var parts = multipart.Parse(bodyBuffer, boundary);
const accountname ="blobstorage0516";
const key = "key";
const containerName="test";
var retryOperations = new azure.ExponentialRetryPolicyFilter();
const blobClient =azure.createBlobService(accountname,key).withFilter(retryOperations);
blobClient.createContainerIfNotExists(containerName, function (error) {
if (error) {
context.log(error);
}
});
var options = {
contentSettings:{contentType: parts[0].type},
metadata: { fileName: parts[0].filename },
blockSize:8*1024*1024,
parallelOperationThreadCount:20,
timeoutIntervalInMs:30*60*1000
};
var stream =getStream(parts[0].data)
context.log("start")
var result="ok"
var speedsummary= blobClient.createBlockBlobFromStream(containerName,parts[0].filename,stream,parts[0].data.length,options,function (error) {
if (error != null) {
result=error
} else {
}})
context.res = { body : { results : result}};
context.done();
};
You also can access the video from the bloburl
I really despair at this problem. I already found some other threads that consider about this problem, but I don't found a solution for me.
I want to upload a mp3 / mp4 file. But with my current solution only pictures are being uploaded.
This question is only about the core functionality of upload a mp3 / mp4 file - I conscious exclude any security checks or kind of this.
PHP:
if(move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/" . $_FILES['file']['name']))
{
echo "Successfully Uploaded Images";
}
else
{
echo "Error while uploading";
}
JS:
file = this.files[i];
if (window.FileReader) {
reader = new FileReader();
reader.onloadend = function(e) {
//showUploadedItem(e.target.result, file.fileName);
};
reader.readAsDataURL(file);
}
if (formdata) {
formdata.append("file", file);
}
if (formdata)
{
$.ajax(
{
url: "upload.php",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success: function(res)
{
document.getElementById("response").innerHTML = res;
}
});
}
EDIT:
I already set the upload_max_filesize to 32 MB.
I got this response from the server:
( ! ) Notice: Undefined index: file in C:\wamp\www\musicplayer_www\public_html\4_upload\upload.php on line 3
Call Stack
# Time Memory Function Location
1 0.0022 134720 {main}( ) ..\upload.php:0
( ! ) Notice: Undefined index: file in C:\wamp\www\musicplayer_www\public_html\4_upload\upload.php on line 3
Call Stack
# Time Memory Function Location
1 0.0022 134720 {main}( ) ..\upload.php:0
EDIT 2:
HTML Form:
<div id="main">
<h1>1. upload track to ftp</h1>
<form method="post" enctype="multipart/form-data" action="upload.php">
<input type="file" name="images" id="images" multiple/>
<button type="submit" id="btn" class="btn btn-default">Upload Files!</button>
</form>
<div id="response"></div>
</form>
</div>
EDIT 3:
In reference to this, there some more limits we have to consider:
post_max_size
upload_max_filesize
memory_limit
So the thought of bluesky is in the right direction.
I think your mp3,mp4 file too large, you can check Maximum allowed size for uploaded file in php.ini, default you can upload file with 2Mb, change upload_max_filesize and restart your server
Use the following:
var data = new FormData();
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file-'+i, file);
});
jQuery.ajax({
url: 'upload.php',
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
alert(data);
}
});