I'm not very practiced in using XMLHttpRequests, but I am working on a drag and drop file converter that takes a zip file and returns one in response. Most of it is working, but I'm not sure how to pick the zip file out of the response. Here's where I'm at:
dropZone[0].ondrop = function(event) {
// Stop the browser from opening the file in the window
event.preventDefault();
dropZone.removeClass('hover');
// Get the file and the file reader
var file = event.dataTransfer.files[0];
// Send the file
var xhr = new XMLHttpRequest();
// xhr.upload.addEventListener('progress', uploadProgress, false);
xhr.onreadystatechange = function(response) {
if (event.target.readyState == 4) {
alert("winner");
if (event.target.status == 200) {
$('#dropZone').text('Upload Complete!');
}
else {
dropZone.text('Upload Failed!');
dropZone.addClass('error');
}
}
};
xhr.open('POST', 'Home/handleFileUpload', true);
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
};
fiddler is showing a 200 with some binary results. How do I make the browswer save/download it as a zip?
Related
Having an issue with uploading images on Tiny. I want to upload the images to folder /images/owner/ I don't want a blob, but rather to upload full files.
I can upload to file_upload.php no problem from test.html. Containing a text input and a file input only. file_upload.php looks like this ...
<?php
/***************************************************
* Only these origins are allowed to upload images *
***************************************************/
$accepted_origins = array("http://localhost", "http://192.168.1.1", "https://example.com/");
/*********************************************
* Change this line to set the upload folder *
*********************************************/
$owner_id=$_POST["owner"];
//$owner_id='15601a2cc3d5b2';
$imageFolder = "images/". $owner_id . "/";
// Don't attempt to process the upload on an OPTIONS request
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header("Access-Control-Allow-Methods: POST, OPTIONS");
return;
}
reset($_FILES);
$temp = current($_FILES);
if (is_uploaded_file($temp['tmp_name'])){
// Sanitize input
if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) {
header("HTTP/1.1 400 Invalid file name.");
return;
}
// Verify extension
if (!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) {
header("HTTP/1.1 400 Invalid extension.");
return;
}
// Accept upload if there was no origin, or if it is an accepted origin
$filetowrite = $imageFolder . $temp['name'];
move_uploaded_file($temp['tmp_name'], $filetowrite);
// Determine the base URL
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? "https://" : "http://";
$baseurl = $protocol . $_SERVER["HTTP_HOST"] . rtrim(dirname($_SERVER['REQUEST_URI']), "/") . "/";
// Respond to the successful upload with JSON.
// Use a location key to specify the path to the saved image resource.
// { location : '/your/uploaded/image/file'}
echo json_encode(array('location' => $baseurl . $filetowrite));
} else {
// Notify editor that the upload failed
header("HTTP/1.1 500 Server Error");
}
?>
This Tiny JS code is on my editor.php page. I don't want a blob that can't be linked to. I want to send an email newsletter and only proper files/images on the server will render...
<script>
tinymce.init({
selector: '#mytextarea',
images_upload_handler: images_upload_handler,
plugins: 'image code',
toolbar: 'undo redo | link image',
/* enable title field in the Image dialog*/
image_title: true,
/* enable automatic uploads of images represented by blob or data URIs*/
automatic_uploads: true,
/*
URL of our upload handler (for more details check: https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_url)
images_upload_url: './js/tinymce/postAcceptor.php',
here we add custom filepicker only to Image dialog
*/
file_picker_types: 'image',
/* and here's our custom image picker*/
file_picker_callback: function (cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
/*
Note: In modern browsers input[type=\"file\"] is functional without
even adding it to the DOM, but that might not be the case in some older
or quirky browsers like IE, so you might want to add it to the DOM
just in case, and visually hide it. And do not forget do remove it
once you do not need it anymore.
*/
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
/*
Note: Now we need to register the blob in TinyMCEs image blob
registry. In the next release this part hopefully won't be
necessary, as we are looking to handle it internally.
*/
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(',')[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
/* call the callback and populate the Title field with the file name */
cb(blobInfo.blobUri(), { title: file.name });
};
reader.readAsDataURL(file);
};
input.click();
},
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
function images_upload_handler (blobInfo, success, failure, progress) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST','https://example.com/myfolder/file-upload.php');
xhr.upload.onprogress = function (e) {
progress(e.loaded / e.total * 100);
};
xhr.onload = function() {
var json;
if (xhr.status === 403) {
failure('HTTP Error: ' + xhr.status, { remove: true });
return;
}
if (xhr.status < 200 || xhr.status >= 300) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
success(json.location);
};
xhr.onerror = function () {
failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
};
formData = new FormData();
formData.append('owner','" . $owner_id . "');
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
};
When i do this from chrome web dev ...
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST','https://example.com/myfolder/file-upload.php');
formData = new FormData();
formData.append('owner','ddddddddd');
formData.append('file', '/home/me/Desktop/image/mail.png');
xhr.send(formData);
I get array(0) {}
I can't send both values, owner and file. I've stacked them in the correct order.
Also have to click upload on the Tiny editor image popup, when i use General it gives me a blob.
No luck. Sorry if this post is kinda verbose. Thought you'd need all the code to help...
I'm using TinyMCE 5 with PHP 7.
Currently:
1. images_upload_handler (working)
Following the TinyMCE guide on Drag-in uploading images, and my own PHP upload AJAX handler, I got an image to upload successfully to my uploads directory:
This correctly uploads the file and keeps the correct name, using AJAX.
It uses a function for images_upload_handler, calling my AJAX handler.
2. file_picker_callback (incomplete)
Following the TinyMCE demo on uploading files, I got these two toolbar buttons (image, media) to show an upload button in their dialogs:
This works for image, not media.
It uses a function for file_picker_callback, uploading its own way.
3. The problem
I can't get the file_picker_callback from 2. to upload from media and I want it to use my own AJAX upload handler anyway, which I can't.
Using the image tool to upload, it will save the file after clicking "Save" in the dialog. But, when used in the media tool, it will not upload or insert anything at all.
It seems that this JavaScript demo provided by TinyMCE has a heavy interaction with the TinyMCE API itself. It has a system of caching and blobs to find the file that TinyMCE uploaded on its own. So pure AJAX-JS knowledge isn't sufficient to tell me how to tell TinyMCE to use my own AJAX upload PHP file. I'd rather just override TinyMCE's upload handler in file_picker_callback so I can use my own PHP upload script to be compatible with the rest of my app.
Goal:
I need a function for file_picker_callback (the file upload button) to use my own AJAX upload handler and preserve the name just as images_upload_handler succeeds in doing.
I am not worried about filename and mimetype validation; I plan to have PHP sanitize and filter later on.
This Question addresses another file uploader and the problem of TinyMCE 4 solutions not always working with TinyMCE 5.
This Question is about image description, and only for images; I want to upload any filetype.
I do not want any dependencies, not even jQuery. Vanilla JS only.
Current Code:
| upload.php :
$temp_file = $_FILES['file']['tmp_name'];
$file_path_dest = 'uploads/'.$_FILES['file']['name'];
move_uploaded_file($temp_file, $file_path_dest);
$json_file_is_here = json_encode(array('filepath' => $file_path_dest));
echo $json_file_is_here;
| tinyinit.js :
tinymce.init({
selector: 'textarea',
plugins: [ 'image media imagetools', ],
automatic_uploads: true,
images_reuse_filename: true,
images_upload_url: 'upload.php',
// From #1. Successful AJAX Upload
images_upload_handler: function(fileHere, success, fail) {
var ajax = new XMLHttpRequest();
ajax.withCredentials = false;
ajax.open('post', 'upload.php');
ajax.upload.onprogress = function (e) {
progress(e.loaded / e.total * 100);
};
ajax.onload = function() {
if (ajax.status == 200) {
if ( (!JSON.parse(ajax.responseText))
|| (typeof JSON.parse(ajax.responseText).filepath != 'string') ) {
fail('Invalid: <code>'+ajax.responseText+'</code>');
return;
}
success(JSON.parse(ajax.responseText).filepath);
} else {
fail('Upload error: <code>'+ajax.status+'</code>');
return;
}
};
var fileInfo = new FormData();
fileInfo.append('file', fileHere.blob(), fileHere.filename());
ajax.send(fileInfo);
},
file_browser_callback_types: 'file image media',
file_picker_types: 'file image media',
// From #2. Neither uploads from "media" nor uses my upload handler
file_picker_callback: function(cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.onchange = function() {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(',')[1];
var blobInfo = blobCache.create(file.name, file, base64);
blobCache.add(blobInfo);
cb(blobInfo.blobUri(), { title: file.name });
};
reader.readAsDataURL(file);
};
input.click();
}
});
Editing #Aulia's Answer :
file_picker_callback: function (cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
// FormData
var fd = new FormData();
var files = file;
fd.append('filetype',meta.filetype);
fd.append("file",files);
var filename = "";
// AJAX
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '/your-endpoint');
xhr.onload = function() {
var json;
if (xhr.status != 200) {
alert('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
alert('Invalid JSON: ' + xhr.responseText);
return;
}
filename = json.location;
reader.onload = function(e) {
cb(filename);
};
reader.readAsDataURL(file);
};
xhr.send(fd);
return
};
input.click();
}
In the configuration you've provided, #2 doesn't have any logic to upload the data to your server. The code from Tiny's documentation you've copied is just for demo purposes and won't allow you to upload files to Tiny's servers.
You will need to setup the file_picker_callback callback to send data similar to images_upload_handler. On your server, you will need to send the URI and title in the response so the following line will be fulfilled:
cb(blobInfo.blobUri(), { title: file.name });
Hope it will helps mate, make your file_picker_callback looks like below codes
file_picker_callback: function (cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
// FormData
var fd = new FormData();
var files = file;
fd.append('filetype',meta.filetype);
fd.append("file",files);
var filename = "";
// AJAX
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '/your-endpoint');
xhr.onload = function() {
var json;
if (xhr.status != 200) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
success(json.location);
filename = json.location;
};
xhr.send(fd);
reader.onload = function(e) {
cb(filename);
};
reader.readAsDataURL(file);
return
};
input.click();
},
I'm using javascript to download multiple files from a webpage.
I'm using FileSaver.js to save the file and this method to download :
function downloadFile(url, success) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (success) success(xhr.response);
}
};
xhr.send(null);
}
together I'm using it like that :
downloadFile(imgurl, function(blob) {
saveAs(blob, "image" + item + ".jpeg");
});
but the problem is im not sure what is the image/video type and the links arent specifying them. (cant take extention from url there's none)
My main issue is recognition between videos and images, probably mp4/png but I prefer being able to determine each file type so I can save it with its extention.
thanks in advance
I'm looking for some way to upload video via XHR, and video convert, my script in XHR looks like.
var files= $("#camera"+id).prop('files');
var file = files[0];
var cList= files.length;
$("#camera"+id).val('');
$("#textarea"+id).val('');
var fd = new FormData();
fd.append("file", file);
fd.append("name", name);
fd.append("desc", desc);
fd.append('id', id);
var xhr = new XMLHttpRequest();
xhr.open("POST", "addUcChallenge.php", true);
xhr.upload.onprogress = function(e)
{
};
xhr.onload = function()
{
if(this.status == 200)
{
cList = 1;
//alert(xhr.responseText);
};
};
if(cList < 1)
{
}
else
{
xhr.send(fd);
}
When I tried to upload video is happen nothink, and when I wanted return some value of file nothing too, but photos are ok, and second think is that I don't know how to handle with video in PHP ( Upload, convert to flv ) Thank you!
For uploading you can use PlUploader code example (that is used for large file uploading and make sure you have edited the max file uploading size in php.ini file if you are using php in backend) and for conversion you have to use the FFMPEG
I want to upload a file trough a XMLHttpRequest. i have looked everywhere for examples and found quite a few. But i cant figer out what it is i am doing wrong. This is my code. The function is triggerd when a button is pressed. It not wrapped in from tags
function upl_kost() {
var url = "proces_data.php?ref=upload_kost";
var hr;
var file = document.getElementById("file_kost");
var formData = new FormData();
formData.append("upload", file.files[0]);
if (window.XMLHttpRequest) {
hr=new XMLHttpRequest();
} else {
hr=new ActiveXObject("Microsoft.XMLHTTP");
}
hr.open("POST", url, true);
hr.setRequestHeader("Content-type", "multipart/form-data");
hr.onreadystatechange = function() {
if(hr.readyState == 4 && hr.status == 200) {
var return_data = hr.responseText;
alert(return_data);
}
}
hr.send(formData);
}
and this function catches it.
if($_GET['ref'] == 'upload_kost') {
var_dump($_FILES);
}
My problem is that the $_FILES stays empty. When i look at the file.files variable in the js its loaded with the data from the file that i am trying to upload.
Thanks!
Reduce your JavaScript down to minimum required for this, then add in some helpful messages you can look in your console for
function upl_kost() {
var xhr = new XMLHttpRequest(),
url = 'proces_data.php?ref=upload_kost',
fd = new FormData(),
elm = document.getElementById('file_kost');
// debug <input>
if (!elm)
console.warn('Element not found');
else if (!(elm instanceof HTMLInputElement))
console.warn('Element not an <input>');
else if (!elm.files || elm.files.length === 0)
console.warn('<input> has no files');
else
console.info('<input> looks okay');
// end debug <input>
fd.append('upload', elm.files[0]);
xhr.addEventListener('load', function () {
console.log('Response:', this.responseText);
});
xhr.open('POST', url);
xhr.send(fd);
}
If you're still having a problem, it may be server-side, e.g. are you performing a redirect before trying to access $_FILES?
Your problem is that you're setting the content type of the request
hr.setRequestHeader("Content-type", "multipart/form-data");
If you ever saw a multipart/formdata post you'll notice the content type header has a boundary
Content-Type: multipart/form-data; boundary=----webko2354645675756
which is missing from your code.
If you do not set the content type header the browser will correctly set it and the required boundary. This will allow the server to properly parse the request body.