How to set name of file downloaded from browser? - html

I'm writing a web application that, among other things, allows users to upload files to my server. In order to prevent name clashes and to organize the files, I rename them once they are put on my server. By keeping track of the original file name I can communicate with the file's owner without them ever knowing I changed the file name on the back end. That is, until they go do download the file. In that case they're prompted to download a file with a unfamiliar name.
My question is, is there any way to specify the name of a file to be downloaded using just HTML? So a user uploads a file named 'abc.txt' and I rename it to 'xyz.txt', but when they download it I want the browser to save the file as 'abc.txt' by default. If this isn't possible with just HTML, is there any way to do it?

When they click a button to download the file, you can add the HTML5 attribute download where you can set the default filename.
That's what I did, when I created a xlsx file and the browser want to save it as zip file.
Download
Download Export

Can't find a way in HTML. I think you'll need a server-side script which will output a content-disposition header. In php this is done like this:
header('Content-Disposition: attachment; filename="downloaded.pdf"');
if you wish to provide a default filename, but not automatic download, this seems to work.
header('Content-Disposition: inline; filename="filetodownload.jpg"');
In fact, it is the server that is directly serving your files, so you have no way to interact with it from HTML, as HTML is not involved at all.

just need to use HTML5 a tag download attribute
codepen live demo
https://codepen.io/xgqfrms/full/GyEGzG/
my screen shortcut.
update answer
whether a file is downloadable depends on the server's response config, such as Content-Type, Content-Disposition;
download file's extensions are optional, depending on the server's config, too.
'Content-Type': 'application/octet-stream',
// it means unknown binary file,
// browsers usually don't execute it, or even ask if it should be executed.
'Content-Disposition': `attachment; filename=server_filename.filetype`,
// if the header specifies a filename,
// it takes priority over a filename specified in the download attribute.
download blob url file
function generatorBlobVideo(url, type, dom, link) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function(res) {
// console.log('res =', res);
var blob = new Blob(
[xhr.response],
{'type' : type},
);
// create blob url
var urlBlob = URL.createObjectURL(blob);
dom.src = urlBlob;
// download file using `a` tag
link.href = urlBlob;
};
xhr.send();
}
(function() {
var type = 'image/png';
var url = 'https://cdn.xgqfrms.xyz/logo/icon.png';
var dom = document.querySelector('#img');
var link = document.querySelector('#img-link');
generatorBlobVideo(url, type, dom, link);
})();
https://cdn.xgqfrms.xyz/HTML5/Blob/index.html
refs
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#download
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#important_mime_types_for_web_developers

Sometimes #Mephiztopheles answer won't work on blob storages and some browsers.
For this you need to use a custom function to convert the file to blob and download it
const coverntFiletoBlobAndDownload = async (file, name) => {
const blob = await fetch(file).then(r => r.blob())
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.style.display = 'none'
a.href = url
a.download = name // add custom extension here
document.body.appendChild(a)
a.click()
window.URL.revokeObjectURL(url)
}

Same code as #Hillkim Henry but with a.remove() improvement
This forces the document to remove the a tag from the body and avoid multiple elements
const coverntFiletoBlobAndDownload = async (file, name) => {
const blob = await fetch(file).then(r => r.blob())
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.style.display = 'none'
a.href = url
a.download = name // add custom extension here
document.body.appendChild(a)
a.click()
window.URL.revokeObjectURL(url)
// Remove "a" tag from the body
a.remove()
}

Well, #Palantir's answer is, for me, the most correct way!
If you plan to use that with multiple files, then i suggest you to use (or make one) PHP Download Manager.
BUT, if you want to make that to one or two files, I will suggest you the mod_rewrite option:
You have to create or edit your .htaccess file on htdocs folder and add this:
RewriteEngine on
RewriteRule ^abc\.txt$ xyz.txt
With this code, users will download xyz.txt data with the name abc.txt
NOTE: Verify if you have already the "RewriteEngine on " on your file, if yes, add only the second for each file you wish to redirect.
Good Luck ;)
(Sorry for my english)

Related

How to set value of an input with type of image file in HTML? [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

Can i send data from one website’s console to another?

So im trying to automate a task at work, and im wondering if theres anyway to send data from the console of one webpage to the console of another web page.
The task i am trying to automate consists of a website that has a prefilled form. I need to get elements from this form, and then copy them into another totally different website. Ive already written a script that pulls the data i need from the form and displays it in the console. Now I need to find a way to send the data (which is simply variables) to the other page’s console. Is this possible?
Keep in mind this is in a work computer, not allowed to download anything on it.
Are you an admin of the webpages and are these pages from the same site? if the answer is yes, i would recommend you use localStorage for saving and retrieving the data then display it to the console.
If it's not your website and you want it to work anyway just create a simple browser extension.
Here are some links to help you get started with extensions
MDN doc
Chrome doc
The idea is for you to target webpage A collect the data and post it to Github
Then target webpage B to read data from your github gist and you dispaly it in the console.
Cheers, i hope it was helpfull
Which server side language are you using ?
Usually for these, you could just have a form which is posting data to another website's form.
Look at this php example :
https://www.ostraining.com/blog/coding/retrieve-html-form-data-with-php/
Correct me If I did not understand your question correctly.
//Store the logs in following way
console.stdlog = console.log.bind(console);
console.logs = [];
console.log = function(){
console.logs.push(Array.from(arguments));
console.stdlog.apply(console, arguments);
}
//copying the logs into a json file
(function(console){
console.save = function(data, filename){
if(!data) {
console.error('Console.save: No data')
return;
}
if(!filename) filename = 'console.json'
if(typeof data === "object"){
data = JSON.stringify(data, undefined, 4)
}
var blob = new Blob([data], {type: 'text/json'}),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
})(console)
console.save(console.logs) //prints the logs in console.json file
// from the console.json file, you can use log information from another page
//Store the logs in following way
console.stdlog = console.log.bind(console);
console.logs = [];
console.log = function(){
console.logs.push(Array.from(arguments));
console.stdlog.apply(console, arguments);
}
localStorage.setItem('Logs', console.logs);
localStorage.getItem('Logs'); // from any browser

Firebase download url in <a> opens csv file in browser

I use Firebase to generate a download link in AngularJS as follows:
self.getDownloadUrl = function(storage_ref) {
var q = $q.defer();
var storage = firebase.storage();
storage.ref(storage_ref).getDownloadURL().then(function(url) {
q.resolve(url);
}).catch(function(error) {
q.reject(error);
});
return q.promise;
};
Then I bind the url to an object scope.downloadUrl. In my DOM I then try to download the file as follows:
Download
However, when I click on this link, it opens my .csv file in the browser (looks like a text file with comma separated, tested it on Chrome and Edge). How can I prevent this and just enforce a proper download?

how to use xhr.overrideMimeType in Chrome / IE Edge?

I have an issue with sending a file (part of a request in form data format).
The issue seems coming from the fact that only in Chrome for Linux the file (which is CVS file, with .csv extension and basically just text) is sent with mimetype (Content-type in request body) Content-Type: application/octet-stream
So, I am trying to override the mimetype to match the same sent by Chrome on Linux which is text/csv.
However the mimetype is apparently not overriden and still send as octet-stream.
My code:
let xhr = new XMLHttpRequest();
let form = new FormData();
form.append('file', file, file.name); // the file is loaded correctly
form.append('payload', JSON.stringify(data)); // data is just a JSON object
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
// we arrive here both on Debian and Windows 10
}
}
xhr.upload.onerror = function() { .... } // no error
xhr.open('POST', 'http://<my_url>', true);
console.log(file.type);
xhr.overrideMimeType("text/csv");
xhr.send(form);
A couple of notes:
console.log(file.type) actually prints "text-csv" but only in Chrome for Linux (Debian specifically). in the other cases (any other browser or platform) nothing is printed
given the previous point, it seems clear to me for some reason any other browser / platform can't recognize the file type, so the file is sent as octet-stream (general binary file)
xhr.overrideMimeType changes the MIME-type of the response, not the request.
I you want to change the MIME-type of the file, just create a new Blob with an explicit file type:
var blob = new Blob([blob], {type: 'text/csv'});
form.append('file', blob, file.name);
The above changes the MIME-type of the file in the uploaded form to "text/csv", as desired.
PS. If you literally want to change the MIME-type of the whole request (instead of just the file), use xhr.setRequestHeader('Content-Type', 'custom MIME type here');. (This only makes sense if you are sending a non-standard or custom data in the xhr.send method).

Correct HTML upload accept attribute for audio/viso

I would like the same input to accept audio/video/image files only.
What is the correct accept attribute value for this?
For images I only need to support gif/jpeg/jpg/png.
currently I am testing this:
accept="image/video/audio/png/gif/jpeg/jpg/mp3/mp4,video/x-m4v,video/*"
You can specify additional MIME types and/or extensions if you need:
accept="video/*,audio/*,image/gif,image/jpeg,image/png,.gif,.jpeg,.jpg,.png"
Documentation: File Upload state (type=file)
Demo Fiddle
function handleFileSelect(evt) {
var validExtensions = ["jpg", "jpeg", "gif", "png", "mp3", "mp4"];
var files = evt.target.files[0];
var ext = files.name.split('.').pop();
if (validExtensions.indexOf(ext) > -1) {
alert("Valid");
} else {
alert("Invalid");
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
This method is based on comparing the extension of the uploaded file with the array of valid extensions. So user can easily validate this by changing the extension of the file.
For ex. Renaming the image.bmp to image.jpg
Reference:
1. For File Extension