I choose an image from the window that open up by clicking a button. Then I display the selected image. I am creating a div, then I create an image element. I get the source of the image from the uploaded file source and then append it in the div. It works fine without any server, But the window prompts for blocked contents and I allow it. But when i run it on the server, the image doesn't show up! Even no permission is asked! Everything works fine in chrome and firefox!
Here is some code,
if(document.all) {
var image = document.createElement("img");
image.src = document.getElementById('fileElem').value;
}
thumbnail.appendChild(image);
This would have worked in older browsers because traditionally <input type="file" /> had a value attribute that returned the full path to the specified file in the local filesystem. However since around 2006 (think IE7+, Firefox 2+, Chrome, etc) browsers no longer provide the full file path, they only provide the file's name without directory information. This is to protect the user's privacy (because uploaded "My Documents" files might contain the user's real-life name, for example).
This affects both uploaded files (the browser no-longer sends the full file path in POST requests, so server-side code only get the filename and file data) as well as local scripts (as you're experiencing yourself).
Related
I am not an HTML/JavaScript developer. I am having to modify some legacy code written by someone who has left.
We have a Python app which acts as a local server with an HTML/JavaScript front end that can be viewed in a browser.
The Python creates a temporary cache file. I would like to give the user the option to save a copy of this temp file to a location of their choice or at least download it to the downloads directory (Windows & Linux)
I've tried adapting some of the ideas from here: https://www.delftstack.com/howto/javascript/javascript-download/
E.g.
const saveAnalysisBtn = document.getElementById("saveAnalysisBtn");
saveAnalysisBtn.addEventListener('click', saveAnalysis);
function saveAnalysis(evt) {
function download(filename) {
var element = document.createElement('a');
// hardcode temp file name just for POC
element.setAttribute('href','file://C:\\tmp\\my_temp_cache.db');
element.setAttribute('download', filename);
document.body.appendChild(element);
element.click();
//document.body.removeChild(element);
}
var filename = "output.txt";
console.log(`Call Download`);
download(filename);
}
In Firefox this gives a security error:
Security Error: Content at
http://127.0.0.1:5000/replay/fapi_15_6_udi.bin may not load or link to
file:///C:/tmp/my_temp_cache.db
Which isn't terribly surprising. (Edge & Chrome give similar errors)
Is there a way to do this? Can be in HTML or JavaScript or Python (though I would like user to see evidence of download taking place in the browser).
Maybe I'm not understanding, but it looks like we're talking about just copying a file from one local location to a user specified location. The file you want to copy is on the machine the user is using? Couldn't you just provide the location in the web page and then just go there in a file explorer, finder, or command line tool to copy it however you want? It would solve the security issue.
But if you're required to create a link, you could create a download process that zips the file up to make a file like "my_temp_cache_db.zip" (or whatever compression tool/extension works best for you), and then provide the link for that. Zip files work through browsers better than some other types of files, and the user just has to unzip it wherever it ended up.
If that's not ideal, you could create a download process that makes a copy of the file and just changes the extension to something like "txt". The user downloads that file and then has to rename it to have the right extension.
I have seen lots of topics, but none of the solutions worked.
My app creates a PDF file with PHP and then retrieves the path into JS. After that I create an Iframe and tell the browser to print it.
The following code works only on chrome, but my POS Printer has a issue with chrome (documented) that creates alot of paper. So the solution is to use another browser...so my guess was to use Firefox.
$('#pdf-iframe').attr('src', json.pathToPdf).after(function()
{
setTimeout(function()
{
document.getElementById('pdf-iframe').contentWindow.focus();
document.getElementById('pdf-iframe').contentWindow.print();
}, 300);
});
In google chrome the PDF Preview is opened, in Firefox I receive the following error:
SecurityError: Permission denied to access property "print" on cross-origin object
What I have tried so far without success:
Use window.frames["pdf-iframe"].focus(); window.frames["pdf-iframe"].print();
Enable/disable pdfjs.disabled
Use imagick to convert to PNG (and it works - it allows to print) however the receipt PDF is broken in two pages (the receipt only has one page) AND it add's automatically headers and footers to the img (like the url; pages number; etc)
Installed "CORSE" extension in order to remove Cross-Origin
Set security.fileuri.strict_origin_policy as FALSE
Saved the PDF as base64_encode and then used <iframe src="data:application/pdf;base64,my_binary_data"
Added header("Access-Control-Allow-Origin: *");
Installed the latest Firefox version
Changed https://sitename to https://www.sitename
Changed the file path to match the path of the source code. The code is being executed in sitename.com/app/files and the file path is sitename.com/public/pdf-files/mypdf.pdf
Instead of retrieving the file path from PHP, read the file directly using header() and readfile() functions
Tried to use a button to open the iframe instead of auto-load/print
I figure I'd demonstrate the problem with an example first,
jsfiddle: http://jsfiddle.net/e2UfM/15/
(Tested with FF 12, and Chrome 18.0.1025.168)
Usage:
Load in a text file from your local machine.
Hit "load file".
Hit "display file size" - note the size.
modify & save the text file on your local machine.
Hit "display file size" again. Note how in webkit browsers (Chrome) the file size changes, but in Firefox it didn't update the file size
Non-webkit browsers do not update their size attribute when users make changes to the local file that they have selected whereas Chrome for example does. Both browsers update the contents of the file.
Is there a way to get Firefox to update the file size similar to how Chrome does in this situation?
Simple Real World Example:
User selects a file that's too large for the form, they hit the submit button and get notified that their file is too large (via an alert, "size" bar (see below), etc)
They modify the file locally, and hit submit again.
In Chrome, the file size updates. When the user hits the submit button again, it will validate it's updated size once more and allow the upload. In Firefox, the user must re-select the file on the form before it will see the file size change.
A partial workaround for Firefox - #ZER0's answer
Real world example (in-depth):
One purpose of the File API is to verify file sizes on the client side before uploading to a server if I'm not mistaken.
Consider the scenario where there is a 2MB upload limit in a form and the user chooses a 1MB file. Both Firefox and Chrome will see that the file size is less than 2MB and add it to the form. Let's also say there is a neat bar that shows how big of a file they have chosen, and if it meats the file size limit or not:
But then the user decides to make a minor change to the contents of that file locally before they submit the form and bump the size over 2MB.
In Google Chrome, I can handle this gracefully on the client side. I can check the file size again when the user submits the form, and verify that it is still in fact under 1MB before sending it to the server. But even before the user submits the form, in Chrome, I can go as far as updating the little bar image dynamically as they make changes locally as such:
This "bar" (or any other form on instant notification such as an alert) is useful if the user is filling out a large form. I'd like the user to know instantly when their file is too large and so that they can correct it then, and not just when they submit the form.
In Firefox, because the file size never updates, it will gladly upload the 2MB file thinking that it is still 1MB! I use server side logic to double check the file size, but I'd rather save a server trip.
How I came across the bug:
The above examples are in place to relate to more people as more people have probably dealt with file uploads in forms vs. using the slice function in the File API. This is specifically how I am running into the issue.
In my form, the user selects a file and when they hit submit only the last 10,000 bytes are displayed on the screen in a textarea to confirm that it's really the file that they want.
Consider a file with a size of 50,000 bytes. A user chooses it in the form, and both Chrome and Firefox show bytes 40,000 - 50,000 in the textarea.
Now the user adds some content to the file, and bumps the same file to 70,000 bytes!
Google Chrome will properly update the textarea to contain bytes 60,000-70,000. In Firefox, because the size will remain constant, it will still only show bytes in the range 40,000-50,000.
Edit: Updated the jsfiddle to demonstrate that FF can still read the updated file contents. It's just that the file size does not change with those new contents.
Edit: https://bugzilla.mozilla.org/show_bug.cgi?id=756503 (bug report)
Edit: Examples have been added & updated in response to #Eduárd Moldován's comment & #ZER0's answer. Thanks!
It seems that you're get the size property from the directly, and because the value in this form element is not changed it's likely that Firefox doesn't update the size property as well.
As workaround, you can check the length of the content you have read. So instead of file.size have evt.target.result.length.
However, it's definitely a bug to me so you have done well to add it on Bugzilla!
Update:
You can still use the string version of slice. Otherwise, if you prefer (or the result is a particular type of data), you can create from evt.target.result a new Blob object (The File Object use this interface) where you can use both size property and slice method.
I have an offline html file that generates and saves a CSV by setting window.location to
data:text/csv;base64,Intfa2V5fSIsInt...
However, in Safari this just brings up the CSV in the browser.
Setting the url to:
data:application/csv;base64,Intfa2V5fSIsInt...
forces Safari to download the file - but it gets a generic file name of just 'Unknown-3'. Is there a way to specify the file name?
First, a warning:application/csv isn't a valid MIME type, so the fact that it "works" for you in this case is purely an implementation quirk that could very well change in the future. (For example, Safari displays application/octet-stream, which I'd expect to download.)
HTML5 does have a new <a download="file.name"> attribute. This forces the browser to download the file to disk; it uses the attribute's value as the default file name. It does work in conjunction with a data URI or a blob URI. (Demo)
However, it is currently only supported by Chrome (14+). Safari 5.1 ignores the attribute.
A possible alternative is to use the Filesystem API, but that gives you a sandboxed folder to work with. You can't—for example—save a file directly to the user's Documents folder. Instead, you can write a file to the sandbox and then redirect to file on the new filesystem schema:
location.assign('filesystem:http://example.com/temporary/somefile.csv');
This should invoke the UA's download mechanism (with the right filename!), but I haven't tested this, so it is possible Safari will just display the file anyway.
According to the RFC 2397 no. There is no way.
Also read this related question.
I display a file open box so the user can select a file on their computer:
<input type="file" id="upload_input"/>
but when I get the file the user chose in Javascript (see code below), which I believe is 'safe' since javascript executes on the client side -- all I get is the file, not the full path -- despite the fact that the full path and filename appear in the field next to the 'Browse' button that input type=file always gives you.
In other words the user selects a file located on his machine for example at c:/aFolder/thefile.rtf.
Then after choosing that file the full path appears in the field next to the 'Browse' button: c:/aFolder/thefile.rtf
Yet when I programmatically retrieve the value of that field, the entire path is stripped off and all I have is the filename:
filename = document.getElementById('upload_input').value;
alert("The selected file name is " + filename);
Why does the input type=file control even bother to show the user the full path if you can't get it programmatically?
It's all happening on the client side after all, it's not like this is a full path on the server.
One other question: I use the filename above and construct a fully qualified path to that file, only for the sake of getting my JWplayer code working. The full path I create for development here is temporary.
In otherwords, when I get the filename above, I do this:
vidFname = ("c:/xampp/htdocs/theWebsite/aFolder/" + filename);
alert("The full path is: " + vidFname);
and then I try to play the video in Jwplayer:
playlist = { file: vidFname };
theJwPlayer().load(playlist);
theJwPlayer().play(true);
but Jwplayer gives me "Permission denied or file not found."
Here is what I had to change to get this to work:
vidFname = ("http://localhost/theWebsite/aFolder/" + filename);
alert("The full path is: " + vidFname);
playlist = { file: vidFname };
theJwPlayer().load(playlist);
theJwPlayer().play(true);
By changing the path to my localhost the above code works -- the video loads and succesffully plays.
NOTE: I don't think this is a 'folder permissions' issue because I can play the exact same file in the same location with a different .FLV player (standalone) app on my computer. So it's not folder permissions in my c:/xampp that's making Jwplayer say 'permission denied or file not found.'
Why won't Jwplayer (or is it Javascript..?) not letting me use a fully-qualified pathname to the file when I call
jwplayer().load() ?
After all, I'm using 'theJwPlayer' in Javascript,' which is running on the client computer, and the file is on the client computer too, so it's not a security issue.
Or is there something I'm missing here? NOTE: I fully apologize if this question is ignorant but at my current level of web programming, which you may have passed LONG ago, this is puzzling, ESPECIALLY the jwplayer().load() not working with a fully qualified path name.
Browsers will not reveal actual file paths to JavaScript code. It's a security thing. You won't be able to get at local files without using the (new, only available in new browsers) HTML5 file handling APIs, and even those won't give you complete file pathnames.
Similarly, when the file input is submitted with a form, the server won't get the full path either.
I think it's not very likely that this media player tool you're working with is designed to work with local files (that is, files on the local file system where the browser is running).