How to upload pre-defined file with XMLHttpRequest? - javascript

Assuming I have a file data.txt and I want to send it using POST with XHR.
I found this. All my google searches have led to the use of FormData object.
<input type="file" id="uploadfile" name="uploadfile" />
<input type="button" value="upload" onclick="upload()" />
<script>
var client = new XMLHttpRequest();
function upload()
{
var file = document.getElementById("uploadfile");
/* Create a FormData instance */
var formData = new FormData();
/* Add the file */
formData.append("upload", file.files[0]);
client.open("post", "/upload", true);
client.setRequestHeader("Content-Type", "multipart/form-data");
client.send(formData); /* Send to server */
}
/* Check the response status */
client.onreadystatechange = function()
{
if (client.readyState == 4 && client.status == 200)
{
alert(client.statusText);
}
}
</script>
This example looks nice however I want the file to be uploaded without the pick of it which isn't the case in this code.
So I thought about putting a custom value in the file input like this :
<input value = "data.txt" type="file" id="uploadfile" name="uploadfile" />
But apparently we just can't do it.
So how can I achieve this with or without using FormData knowing that I want to send this file without picking it ?

What you're asking is not possible for very obvious security reasons.
Imagine a website that could just grab any file it wanted from your machine and upload it to its server without any interaction or authorisation on your part.
What you can do, though, to go some way towards ensuring the correct file is uploaded is add a server side check that the name of the file being uploaded is data.txt before processing.

Related

Form with Image Input type JavaScript React.js [duplicate]

How can I set the value of this?
<input type="file" />
You cannot set it to a client side disk file system path, due to security reasons.
Imagine:
<form name="foo" method="post" enctype="multipart/form-data">
<input type="file" value="c:/passwords.txt">
</form>
<script>document.foo.submit();</script>
You don't want the websites you visit to be able to do this, do you? =)
You can only set it to a publicly accessible web resource as seen in this answer, but this is clearly not the same as a client side disk file system path and it's therefore useless in that context.
You can't.
The only way to set the value of a file input is by the user to select a file.
This is done for security reasons. Otherwise you would be able to create a JavaScript that automatically uploads a specific file from the client's computer.
Not an answer to your question (which others have answered), but if you want to have some edit functionality of an uploaded file field, what you probably want to do is:
show the current value of this field by just printing the filename or URL, a clickable link to download it, or if it's an image: just show it, possibly as thumbnail
the <input> tag to upload a new file
a checkbox that, when checked, deletes the currently uploaded file. note that there's no way to upload an 'empty' file, so you need something like this to clear out the field's value
You can't. And it's a security measure. Imagine if someone writes JS that sets file input value to some sensitive data file?
I have write full example for load URL to input file, and preview
you can check here
1
https://vulieumang.github.io/vuhocjs/file2input-input2file/
in short you can use this function
function loadURLToInputFiled(url){
getImgURL(url, (imgBlob)=>{
// Load img blob to input
// WIP: UTF8 character error
let fileName = 'hasFilename.jpg'
let file = new File([imgBlob], fileName,{type:"image/jpeg", lastModified:new Date().getTime()}, 'utf-8');
let container = new DataTransfer();
container.items.add(file);
document.querySelector('#file_input').files = container.files;
})
}
// xmlHTTP return blob respond
function getImgURL(url, callback){
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
As everyone else here has stated: You cannot upload just any file automatically with JavaScript.
HOWEVER! If you have access to the information you want to send in your code (i.e., not C:\passwords.txt), then you can upload it as a blob-type, and then treat it as a file.
What the server will end up seeing will be indistinguishable from someone actually setting the value of <input type="file" />. The trick, ultimately, is to begin a new XMLHttpRequest() with the server...
function uploadFile (data) {
// define data and connections
var blob = new Blob([JSON.stringify(data)]);
var url = URL.createObjectURL(blob);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'myForm.php', true);
// define new form
var formData = new FormData();
formData.append('someUploadIdentifier', blob, 'someFileName.json');
// action after uploading happens
xhr.onload = function(e) {
console.log("File uploading completed!");
};
// do the uploading
console.log("File uploading started!");
xhr.send(formData);
}
// This data/text below is local to the JS script, so we are allowed to send it!
uploadFile({'hello!':'how are you?'});
So, what could you possibly use this for? I use it for uploading HTML5 canvas elements as jpg's. This saves the user the trouble of having to open a file input element, only to select the local, cached image that they just resized, modified, etc.. But it should work for any file type.
You need to create a DataTransfer and set the .files property of the input.
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);//your file(s) reference(s)
document.getElementById('input_field').files = dataTransfer.files;
the subject is very old but I think someone can need this answer!
<input type="file" />
<script>
// Get a reference to our file input
const fileInput = document.querySelector('input[type="file"]');
// Create a new File object
const myFile = new File(['Hello World!'], 'myFile.txt', {
type: 'text/plain',
lastModified: new Date(),
});
// Now let's create a DataTransfer to get a FileList
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);
fileInput.files = dataTransfer.files;
</script>
Define in html:
<input type="hidden" name="image" id="image"/>
In JS:
ajax.jsonRpc("/consulta/dni", 'call', {'document_number': document_number})
.then(function (data) {
if (data.error){
...;
}
else {
$('#image').val(data.image);
}
})
After:
<input type="hidden" name="image" id="image" value="/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8U..."/>
<button type="submit">Submit</button>
Actually we can do it.
we can set the file value default by using webbrowser control in c# using FormToMultipartPostData Library.We have to download and include this Library in our project. Webbrowser enables the user to navigate Web pages inside form.
Once the web page loaded , the script inside the webBrowser1_DocumentCompleted will be executed.
So,
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
FormToMultipartPostData postData =
new FormToMultipartPostData(webBrowser1, form);
postData.SetFile("fileField", #"C:\windows\win.ini");
postData.Submit();
}
Refer the below link for downloading and complete reference.
https://www.codeproject.com/Articles/28917/Setting-a-file-to-upload-inside-the-WebBrowser-com

Upload file to DOM using just JavaScript [duplicate]

How can I set the value of this?
<input type="file" />
You cannot set it to a client side disk file system path, due to security reasons.
Imagine:
<form name="foo" method="post" enctype="multipart/form-data">
<input type="file" value="c:/passwords.txt">
</form>
<script>document.foo.submit();</script>
You don't want the websites you visit to be able to do this, do you? =)
You can only set it to a publicly accessible web resource as seen in this answer, but this is clearly not the same as a client side disk file system path and it's therefore useless in that context.
You can't.
The only way to set the value of a file input is by the user to select a file.
This is done for security reasons. Otherwise you would be able to create a JavaScript that automatically uploads a specific file from the client's computer.
Not an answer to your question (which others have answered), but if you want to have some edit functionality of an uploaded file field, what you probably want to do is:
show the current value of this field by just printing the filename or URL, a clickable link to download it, or if it's an image: just show it, possibly as thumbnail
the <input> tag to upload a new file
a checkbox that, when checked, deletes the currently uploaded file. note that there's no way to upload an 'empty' file, so you need something like this to clear out the field's value
You can't. And it's a security measure. Imagine if someone writes JS that sets file input value to some sensitive data file?
I have write full example for load URL to input file, and preview
you can check here
1
https://vulieumang.github.io/vuhocjs/file2input-input2file/
in short you can use this function
function loadURLToInputFiled(url){
getImgURL(url, (imgBlob)=>{
// Load img blob to input
// WIP: UTF8 character error
let fileName = 'hasFilename.jpg'
let file = new File([imgBlob], fileName,{type:"image/jpeg", lastModified:new Date().getTime()}, 'utf-8');
let container = new DataTransfer();
container.items.add(file);
document.querySelector('#file_input').files = container.files;
})
}
// xmlHTTP return blob respond
function getImgURL(url, callback){
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
As everyone else here has stated: You cannot upload just any file automatically with JavaScript.
HOWEVER! If you have access to the information you want to send in your code (i.e., not C:\passwords.txt), then you can upload it as a blob-type, and then treat it as a file.
What the server will end up seeing will be indistinguishable from someone actually setting the value of <input type="file" />. The trick, ultimately, is to begin a new XMLHttpRequest() with the server...
function uploadFile (data) {
// define data and connections
var blob = new Blob([JSON.stringify(data)]);
var url = URL.createObjectURL(blob);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'myForm.php', true);
// define new form
var formData = new FormData();
formData.append('someUploadIdentifier', blob, 'someFileName.json');
// action after uploading happens
xhr.onload = function(e) {
console.log("File uploading completed!");
};
// do the uploading
console.log("File uploading started!");
xhr.send(formData);
}
// This data/text below is local to the JS script, so we are allowed to send it!
uploadFile({'hello!':'how are you?'});
So, what could you possibly use this for? I use it for uploading HTML5 canvas elements as jpg's. This saves the user the trouble of having to open a file input element, only to select the local, cached image that they just resized, modified, etc.. But it should work for any file type.
the subject is very old but I think someone can need this answer!
<input type="file" />
<script>
// Get a reference to our file input
const fileInput = document.querySelector('input[type="file"]');
// Create a new File object
const myFile = new File(['Hello World!'], 'myFile.txt', {
type: 'text/plain',
lastModified: new Date(),
});
// Now let's create a DataTransfer to get a FileList
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);
fileInput.files = dataTransfer.files;
</script>
You need to create a DataTransfer and set the .files property of the input.
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);//your file(s) reference(s)
document.getElementById('input_field').files = dataTransfer.files;
Define in html:
<input type="hidden" name="image" id="image"/>
In JS:
ajax.jsonRpc("/consulta/dni", 'call', {'document_number': document_number})
.then(function (data) {
if (data.error){
...;
}
else {
$('#image').val(data.image);
}
})
After:
<input type="hidden" name="image" id="image" value="/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8U..."/>
<button type="submit">Submit</button>
Actually we can do it.
we can set the file value default by using webbrowser control in c# using FormToMultipartPostData Library.We have to download and include this Library in our project. Webbrowser enables the user to navigate Web pages inside form.
Once the web page loaded , the script inside the webBrowser1_DocumentCompleted will be executed.
So,
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
FormToMultipartPostData postData =
new FormToMultipartPostData(webBrowser1, form);
postData.SetFile("fileField", #"C:\windows\win.ini");
postData.Submit();
}
Refer the below link for downloading and complete reference.
https://www.codeproject.com/Articles/28917/Setting-a-file-to-upload-inside-the-WebBrowser-com

Is there a possibility in rename the files of a html fileinput prior to posting

I have a HTML form with various fields and some fileinputs.
The problem is, that the webserver runs on a windows machine, and some users upload file from mac os or linux with charachters not allowed on windwos, such as: : and ?.
The filehandler (Axon.Ivy / JAVA) which fetches the files cannot work with theses charachters and throws an exception. I have no possibility to change the filehandler.
Since the orignal filenames are irrelevant, my optimal solution would be, to rename the files, or manipulate the filename attribute in the POST data before the actual POST happens. Preferrably with javascript.
Is there any possible way to achieve this?
Thanks in advance!
Yes, with the FormData API, you can set an other name to your files before sending it through AJAX :
...
var form = new FormData();
form.append(someField, someInput.value);
// when appending a File or a Blob, the third param is the name of the File
form.append('fileField', fileinput.files[0], filename);
xhr.send(form);
sub.onclick = e => {
var form = new FormData();
form.append('fileField', inp.files[0], 'myFile.ext');
console.log(form.get('fileField'));
}
<input type="file" id="inp">
<button id="sub">submit</button>

How to upload file using pure vanilla javascript and php?

I have an existing html form which uploads a file to the server as soon as the user selects an image file.
I have done something like this.
//html code
<input type="file" id="photo" name="photo" accept="image/*" />
// the usual html stuff
document.getElementById('photo').addEventListener("change",uploadImage);
function uploadImage()
{
var xhr = new XMLHttpRequest();
xhr.open("POST","/upload.php",true);
xhr.setRequestHeader("Content-type","image");
var file = document.getElementById('photo').files[0];
if(file)
{
var formdata = new FormData();
formdata.append("pic",file);
xhr.send(formdata);
}
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200)
{
//some code
}
};
}
But in my php file, I can't access this uploaded file. The $_POST array seems to be empty. I did a print_r for $_POST and it gave Array(). What am I doing wrong?
You are using FormData which works very much the same way a normal form does.
First of all, in PHP files will not be in $_POST but instead in $_FILES, see the documentation.
What that documentation does mention, along with the $_FILES buffer, is that you need to use the multipart/form-data encoding, any FormData transferred through an XMLHttpRequest will have this set by default, though you may want to check it if the $_FILES remain empty.
You should remove the xhr.setRequestHeader("Content-type","image"); and let the XHR object handle it, of - if that doesn't work - add
xhr.setRequestHeader("Content-type","multipart/form-data");
There is a pretty nice example right here at stackoverflow

How do I send file(s) via ajax without using html form?

I am experiencing difficulties with uploading files via ajax without sing html form.
My case is like this:
I have a textarea
I would like to zip the content of that textarea and upload it to the server via AJAX (right now I am using JSZip)
For testing purpose, I try to create a dummy zip file to send like this (not getting textarea content):
var zip = new JSZip();
zip.file("hello1.txt", "Hello First World\n");<br/>
zip.file("hello2.txt", "Hello Second World\n");<br/>
var content = zip.generate();
Then I use Jquery ajax method to send, like this:
$.post("the_url",
{
GradeRequest : {
submitter_id : "foobar",
evaluationset_id : 9,
mode : 1,
source_file : "a.cpp",
file: content
}
}
);
But the file is not received on the server.
I have read question in How can I upload files asynchronously?, but all solutions are using html form. Is there any solution which does not involve any html form ?
Thanks in advance.
In the server side, I'm using Yii PHP Framework:
$model = $this->model;
if ($model !== null && isset($_POST['GradeRequest'])) {
$model->setAttributes($_POST['GradeRequest']);
if ($model->validate()) {
if (isset($_FILES['GradeRequest']['tmp_name']['file']) && $_FILES['GradeRequest']['tmp_name']['file'] !== "") {
$model->file = file_get_contents($_FILES['GradeRequest']['tmp_name']['file']);
$model->source_file = $_FILES['GradeRequest']['name']['file'];
}
$this->setReply(true, "Ok");
$model->client_id = $this->clientId;
$model->request_id = $this->requestRecord->id;
$model->save();
} else {
$this->setReply(false, $model->getErrors());
}
}
As a proof of concept, I have created a form version like this and it works (the file got uploaded to the server):
<form enctype="multipart/form-data" method="post" action="[the_url]>
EvaluationSet id: <input type="text" name="GradeRequest[evaluationset_id]" /><br />
<input type="hidden" name="GradeRequest[mode]" value="0" />
<input type="hidden" name="GradeRequest[submitter_id]" value="Someone" />
Source file : <input type="text" name="GradeRequest[source_file]" /><br />
File : <input type="file" name="GradeRequest[file]" /><br />
<input type="submit" />
There the FormData object that can help you (it's part of the so called xmlHttpRequest version 2): this is a compatibility chart, with some linked references and examples.
With that, you can add key/value pairs to the POST form, including File objects, and send it all via the common send method of xmlHttpRequest.
File objects can be easily retrieved using a <input type="file"> element, or even using drag & drop from your desktop.
If you want to upload some file content as a file, you'll have to create a Blob. This feature is still experimental but supported by Chrome and Firefox (at least... and Safari I guess?):
var builder = new BlobBuilder();
builder.append(content);
var blob = builder.getBlob("application/zip");
Keep in mind that at this moment you'll have to use MozBlobBuilder in Firefox and WebKitBlobBuilder in Chrome instead.
In some tutorials I've seen that the string is actually converted into a Uint8Array first. Maybe that's based on a older reference, because the append method of BlobBuilder should accept plain strings too. Never tried it though.
If your content is a Base64 encoded string, you'll have to convert it using atob (should be supported by every browser that also supports Blob and FormData).
Edit: BlobBuilder is now deprecated due to the new draft of the Blob constructor. So everything you'll have to do to get the Blob is:
var blob = new Blob([content], "application/zip");
The rest is quite simple:
var form = new FormData();
form.append("file", blob);
The problem here is that the file name on the server side is unpredictable and depends on the user agent. I've seen some uses of append with a third parameter specifying the file name, but I guess it's a good idea to send the actual file name to a separate key/value pair in the FormData object.
I finally get it through !! Many thanks for MaxArt.
Basically, it is what MaxArt has said with Uint8Array conversion. I got the conversion reference from Eric Bidelman here.
Here's how I've done it:
var zip = new JSZip();
zip.file("hello1.txt", "Hello First World\n");
zip.file("hello2.txt", "Hello Second World\n");
var content = zip.generate(); //Generate dummy zip file (adjust to your need)
var oBlob = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder)(); //Instantiate blob builder
var raw = atob(content); //decode the base64 string
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) { //convert to uInt8Array
uInt8Array[i] = raw.charCodeAt(i);
}
oBlob.append(uInt8Array.buffer); //append it to blobbuilder
oMyForm.append("GradeRequest[file]", oBlob.getBlob("application/zip")); //because you create a zip file, so get the zip type
//send it
var oReq = new XMLHttpRequest();
oReq.open("POST", "{{the_url}}");
oReq.send(oMyForm);

Categories

Resources