HTML5 has a very good file upload API. If your application deals with uploading image files, you can make users life even easier by allowing her to paste image data from the OS clipboard. Here, HTML5 clipboard API will come to the rescue. In this article, we will build a complete implementation.
First, create a basic HTML5 page with a <div> where we will paste data.
<!DOCTYPE html> <html> <head> <script type="text/javascript"> //Code will go here </script> </head> <body> <div style="width: 200px; height: 200px; background: grey" id="pasteTarget"> Click and paste here. </div> </body> </html>
Next, within the <script> element, add this function to register the paste event handler.
window.onload = function() { document.getElementById("pasteTarget"). addEventListener("paste", handlePaste); };
Implement handlePaste() as follows:
function handlePaste(e) { for (var i = 0 ; i < e.clipboardData.items.length ; i++) { var item = e.clipboardData.items[i]; console.log("Item type: " + item.type); if (item.type.indexOf("image") != -1) { uploadFile(item.getAsFile()); } else { console.log("Discarding non-image paste data"); } } }
The getAsFile() method gives us access to the image data as a HTML5 file object. We can now use XMLHttpRequest Level 2 API to upload the data using Ajax. Implement uploadFile() as follows.
function uploadFile(file) { var xhr = new XMLHttpRequest(); xhr.upload.onprogress = function(e) { var percentComplete = (e.loaded / e.total) * 100; console.log("Uploaded: " + percentComplete + "%"); }; xhr.onload = function() { if (xhr.status == 200) { alert("Sucess! Upload completed"); } else { alert("Error! Upload failed"); } }; xhr.onerror = function() { alert("Error! Upload failed. Can not connect to server."); }; xhr.open("POST", "FileUploader", true); xhr.setRequestHeader("Content-Type", file.type); xhr.send(file); }
That’s it for the client side. Now, you can write a server side handler, for example a Servlet, to receive the pasted image data.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { InputStream is = request.getInputStream(); //Read the file contents from the input stream byte buff[] = new byte[256]; int len; System.out.println("Dumping paste data of type: " + request.getContentType()); while ((len = is.read(buff)) > 0) { //Do something with the buffer } }
For a fully working example, grab this GitHub repo.
Thank you so much for this compact and complete example!
For a proof of concept, it was very easy to adopt it to Python using Flask on the server side:
@app.route(‘/FileUploader’, methods=[‘POST’])
def fileUploader():
app.logger.info(‘data: %r’ % len(request.data))
file(‘test.png’, ‘w’).write(request.data)
return ‘ok’ # to send the status_code 200
hi , i use the flask as server, it save the image as test.png, but the image can not open, i use some screen capture soft to get the image to the clipboard and paste. could you help me?
would be even better if you included a link to a working web page. I couldn’t get it to work
Good point. I have added a link to a GitHub repo at the bottom of the post. Here is a direct link: https://github.com/bibhas2/PasteTest
Hi, thanks for the great example. Works perfectly in Google Chrome, however, in the Safari, IE and Firefox seems it doesn’t work. Any idea what’s going wrong?
Bp7
Firefox Support HTML5 clipboard API(https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent) which is different form Chrome’s implementation. Until now(2014/10/24) IEs don’t support this API. Maybe Zero Clipboard would be helpfull.
Thank you for the useful documentation. I haven’t been able to use it directly because I’m working with grails / groovy so I had to make a few adaptation, but the code is quite the same.
I also needed to redirect the written image to an appropriate folder inside the appserver to be backed up. For anyone who had the same issue here is the grails controller action implementation, as you can see the arrays has been changed to groovy lists and the save path has been changed to application location :
def pasteDocument() {
//render (“image reçue”);
String mimeType = request.getContentType();
String extension = null;
def supportedFormatTable = [
[“image/png”, “png”],
[“image/jpeg”, “jpg”],
[“image/gif”, “gif”]
];
//logger.info(“Paste data of type: ” + request.getContentType());
for (int i = 0; i 0) {
os.write(buff, 0, len);
}
os.close();
//Show the file name in browser
//PrintWriter out = response.getWriter();
//render(“Save request with params” + params);
render(“Saved image to: ” + saveTo.getAbsolutePath());
}
Anything fo PHP side?
Hi, I don’t know how to work with PHP to read data from a request body stream. But this should be a fairly common task and well documented somewhere.
PHP code to receive raw http data (works on PHP7)
<?php
$entityBody = file_get_contents('php://input');
file_put_contents("/tmp/fileupload", $entityBody);
This is excellent, thank you. Any advice on how to implement this in a django webpage?