I was looking a long time for the solution, but I can not find any. Is there any possibility to upload picture from clipboard to file on server (by pressing ctrl+v) ?
It could work for Chrome.
Use PHP, Javascript, jquery, or maybe sth else? Some external extension for chrome?
Thanks a lot.
You can try:
https://github.com/layerssss/paste.js
Or
On paste event and clipboard API
http://www.w3schools.com/jsref/event_onpaste.asp
https://www.w3.org/TR/clipboard-apis/
How does the paste image from clipboard functionality work in Gmail and Google Chrome 12+?
After you get image in javascript you can send base64 encoded image to server with AJAX. At server-side, you can decode it and write to a file.
Note: This works if you copy image inside browser (from other tab or window). It doesn't work when you copy image from desktop.
This is from an example with angular2 typescript that works for my project. Hope it helps someone. Logic is same for other cases as-well.
angular-clipboard-event.html
<textarea placeholder="Type a message" (paste)="onPaste($event)"></textarea>
<!-- Place to render the image -->
<img #imgRenderer />
angular-clipboard-event.ts
// Reference to the dom element
#ViewChild('imgRenderer') imgRenderer: ElementRef;
onPaste(event: any) {
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
let blob = null;
for (const item of items) {
if (item.type.indexOf('image') === 0) {
blob = item.getAsFile();
}
}
// load image if there is a pasted image
if (blob !== null) {
const reader = new FileReader();
reader.onload = (evt: any) => {
console.log(evt.target.result); // data url!
this.imgRenderer.nativeElement.src = evt.target.result;
};
reader.readAsDataURL(blob);
}
}
Here is a live implementation:
https://stackblitz.com/edit/angular-f7kcny?file=app/app.component.ts
Related
I am using a plugin called dropzone which leaves rendering the image pretty much how to the user.
so I have done this
<Dropzone
onDrop={this.handleDropChange}}>
<p>
Try dropping some files here, or click to select files to upload.
</p>
</Dropzone>
#observable files = [];
#action
handleDropChange = (files) => {
files.forEach(file => {
this.loadFile(file);
});
}
#action
loadFile(file){
const reader = new FileReader();
reader.addEventListener('load',() => {
runInAction(() => {
this.files.push({file: file, preview: reader.result, uploaded: false})
window.URL.revokeObjectURL(reader.result);
});
},false);
// reader.readAsDataURL(file.fileObject);
}
<img src={this.props.preview} />
Problem is though when I drag in say 500 images it takes awhile for them to render on the screen. I think reactjs is having a hard time as it is essentially re-rendering 500 times since each "file reader load" causes a new item to be put into the files array.
Is there away to batch this or first do all the loading then re-render?
revokeObjectURL is for object url's and not meant for other strings|urls|base64.
You can create a objectURL by calling URL.createObjectURL like so:
var url = URL.createObjectURL(file || blob)
var image = new Image()
image.src = url
document.body.appendChild(image)
There is no need to use FileReader and read all the content encode it as base64 then let the browser decode it back into binary. that is a waste of resource...
revoking the objecturl should be done when you no longer need the url
In my web application I have supported user to upload any type of document (.png, .jpg, .docx, .xls, ... ) I'm trying to implement download functionality for these documents.
In Google Chrome if you click on Download link Save dialog is shown for all above documents.
In Mozilla Firefox for docx and xls works fine, Save dialog is shown but for .png and .jpg download tag is not working as expected i.e., download dialog or Save dialog does not appear, it directly open that image.
My code:
Download
I have tried almost all solutions mentioned on stackoverflow and suggested by Google. But most of them says that 'check firefox version' and other changes like:
try adding the element to the DOM before triggering the click
Remove filename from download tag it is of boolean type and etc.
I have also tried w3schools lesson on anchor tag and download attribute but nothing seems to be working.
My Mozilla Firefox version is: 38.0.5
P.S.: in chrome as well as in firefox .docs, .xls, .pdf documents work fine, problem is for .png and .jpg in firefox.
Firefox will handle png and jpeg using default handling, which is to inline them in the document. When clicking a link, even if download attribute is defined, seem to make Firefox think it has a new image ignoring the download aspect of it. This may be a temporary bug.
Here is a way, admittedly not super-elegant, to get around this problem forcing the image to be interpreted as an octet-stream.
It does not work inline on Stackoverflow so you have to test it on jsFiddle.
The code does the following:
Scans the document for a-tags.
Those which has data-link set will have a common click-handler attached.
When clicked the link is extracted from the data-link attribute (href is se to #), loaded as an ArrayBuffer via XHR (CORS requirements applies, not a problem in this case), and is converted to an Object-URL with the Blob set to mime-type octet/stream
The Object URL is set as window.location to redirect to this binary data which will make the browser ask user to download the file instead.
var links = document.querySelectorAll("a"), i = 0, lnk;
while(lnk = links[i++]) {
if (lnk.dataset.link.length) lnk.onclick = toBlob;
}
function toBlob(e) {
e.preventDefault();
var lnk = this, xhr = new XMLHttpRequest();
xhr.open("GET", lnk.dataset.link);
xhr.responseType = "blob";
xhr.overrideMimeType("octet/stream");
xhr.onload = function() {
if (xhr.status === 200) {
window.location = (URL || webkitURL).createObjectURL(xhr.response);
}
};
xhr.send();
}
Example tag:
Click to download
The drawback is that you'll loose the extension in the filename.
This is also possible to do using a Data-URL, but a data-url has a 166% overhead compared to using ArrayBuffer and a blob.
I had a similar problem with firefox not handling the download attribute, even for same-domain files.
My target files are actually hosted on AWS, so they are cross-domain. I got around this with a same-domain endpoint that downloads the remote file and pipes it to the client.
const express = require('express')
const {createWriteStream} = require('fs')
const downloadVideo = (url) => { return new Promise((resolve, reject) => {
const filePath = `/tmp/neat.mp4`
const ws = createWriteStream(filePath)
request(url, {}, (error, response, body) => {
if(error) { return reject(error) }
resolve(filePath)
}).pipe(ws)
})}
app.get('/api/download', async (req, res) => {
const videoPath = await downloadVideo(req.query.url)
res.sendFile(videoPath)
})
On the client, I send the file path to the download endpoint to get a blob back, which is then converted to an object url. From there, it's standard download attribute stuff.
async download(remoteFilePath){
const a = document.createElement('a')
const dlURL = `/api/download?url=${encodeURIComponent(remoteFilePath)}`
const blob = await fetch(dlURL).then(res => res.blob())
a.href = URL.createObjectURL(blob)
a.setAttribute('download', 'cool.mp4')
document.body.appendChild(a)
a.click()
a.remove()
}
As you are using HTML5 attribute, each browser handling differently. So use https://github.com/dcneiner/Downloadify for client side forceful download instead of viewing in browser.
I need to upload an image, something like this
<form>
<input type="file">
</form>
However, I want to crop/resize the file before uploading. The cropping and resize is no problem, but how do I get the base64 from the input file element? In IE10 and the other browsers I can it like this:
if (this.files.length === 0) {
return;
}
var file = this.files[0];
if (file.type.match(/image.*/)) {
var reader = new FileReader();
reader.onload = function (event) {
cropAndResize(event.target.result);
};
reader.readAsDataURL(file);
}
However, in IE9 this.files is undefined. How can I access the base64 of the uploaded image (without a round trip to the backend of course!) in IE9 ?
Here is a jsfiddle
IE9 does not support the FileReader API and therefore cannot do what you want using pure JavaScript. If you want IE9 support, then you'd need to use something like this Flash solution in order to achieve the same result.
I am planning to create a application on my local . I need a javascript code that to render the content from whichever file I am selecting from my system using html file-upload input box. Referred to the below link but
http://www.alecjacobson.com/weblog/?p=1645 where the code is not compatible for other browsers,
Thanks in Advance
For security reasons you can't open a file from the browser. What you can actually do is upload it to the server and then write it back to the page.
To upload the file I suggest you uploadify or jquery upload.
You are welcome.
If you don't care about the cross-browsing support then:
<input id="file" type="file" multiple="" onchange="startRead()">
<pre><code id="output"></code></pre>
function startRead() {
//obtain input element through DOM
var file = document.getElementById('file').files[0];
if (file) {
getAsText(file);
}
}
function getAsText(readFile) {
var reader;
try {
reader = new FileReader();
} catch (e) {
document.getElementById('output').innerHTML = "Error: seems File API is not supported on your browser";
return;
}
// Read file into memory as UTF-8
reader.readAsText(readFile, "UTF-8");
// handle success and errors
reader.onload = loaded;
reader.onerror = errorHandler;
}
function loaded(evt) {
// Obtain the read file data
var fileString = evt.target.result;
document.getElementById('output').innerHTML = fileString;
}
function errorHandler(evt) {
if (evt.target.error.code == evt.target.error.NOT_READABLE_ERR) {
// The file could not be read
document.getElementById('output').innerHTML = "Error reading file..."
}
}
We are developing kinds of web-based GUI editor. This issue have been the problem for long time.
As I know, the method in the site you mentioned is the only way. We are using HTML5 File System.
Before this, We've considered using kinds of Flash module, local web server, dropbox, ...
I noticed a blog post from Google that mentions the ability to paste images directly from the clipboard into a Gmail message if you're using the latest version of Chrome. I tried this with my version of Chrome (12.0.742.91 beta-m) and it works great using control keys or the context menu.
From that behavior I need to assume that the latest version of webkit used in Chrome is able to deal with images in the Javascript paste event, but I have been unable to locate any references to such an enhancement. I believe ZeroClipboard binds to keypress events to trigger its flash functionality and as such wouldn't work through the context menu (also, ZeroClipboard is cross-browser and the post says this works only with Chrome).
So, how does this work and where the enhancement was made to Webkit (or Chrome) that enables the functionality?
I spent some time experimenting with this. It seems to sort of follow the new Clipboard API spec. You can define a "paste" event handler and look at event.clipboardData.items, and call getAsFile() on them to get a Blob. Once you have a Blob, you can use FileReader on it to see what's in it. This is how you can get a data url for the stuff you just pasted in Chrome:
document.onpaste = function (event) {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
console.log(JSON.stringify(items)); // might give you mime types
for (var index in items) {
var item = items[index];
if (item.kind === 'file') {
var blob = item.getAsFile();
var reader = new FileReader();
reader.onload = function (event) {
console.log(event.target.result); // data url!
};
reader.readAsDataURL(blob);
}
}
};
Once you have a data url you can display the image on the page. If you want to upload it instead, you could use readAsBinaryString, or you could put it into an XHR using FormData.
Edit: Note that the item is of type DataTransferItem. JSON.stringify might not work on the items list, but you should be able to get mime type when you loop over items.
The answer by Nick seems to need small changes to still work :)
// window.addEventListener('paste', ... or
document.onpaste = function (event) {
// use event.originalEvent.clipboard for newer chrome versions
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
console.log(JSON.stringify(items)); // will give you the mime types
// find pasted image among pasted items
var blob = null;
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") === 0) {
blob = items[i].getAsFile();
}
}
// load image if there is a pasted image
if (blob !== null) {
var reader = new FileReader();
reader.onload = function(event) {
console.log(event.target.result); // data url!
};
reader.readAsDataURL(blob);
}
}
Example running code: http://jsfiddle.net/bt7BU/225/
So the changes to nicks answer were:
var items = event.clipboardData.items;
to
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
Also I had to take the second element from the pasted items (first one seems to be text/html if you copy an image from another web page into the buffer). So I changed
var blob = items[0].getAsFile();
to a loop finding the item containing the image (see above)
I didn't know how to answer directly to Nick's answer, hope it is fine here :$ :)
As far as I know -
With HTML 5 features(File Api and the related) - accessing clipboard image data is now possible with plain javascript.
This however fails to work on IE (anything less than IE 10). Don't know much about IE10 support also.
For IE the optiens that I believe are the 'fallback' options are
either using Adobe's AIR api
or
using a signed applet