Save a <canvas> as a file in a form
Using Canvas method toDataURL, I would like to be able to save the image on the server side (using Rails).
With toDataURL string, how to use it in a form that can be seen as a file a开发者_开发知识库ttachment in a HTML form ?
Solution using jQuery, Paperclip, datafy.rb http://gist.github.com/397615
Here is my solution:
- The problem: Compact uploaded images of any size before sending it to the server, which will save the image.
- Files involved: 2 ASP pages: one that will act client-side and another server-side.
The Presentation page:
<html>
<!-- by arturmariojr@gmail.com - on december/2012 -->
<script language='javaScript'>
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
} else {
alert('Este Browser não suporte a API Files');
}
function Compactar(Elemento) {
var file = document.getElementById(Elemento),
reader = new FileReader(), // métodos assíncronos, por isso os eventos!
form = document.getElementById('frmFotos');
//alert(file.id);
reader.readAsDataURL(file.files[0]); // aqui a abertura do arquivo, que irá disparar a função acima
reader.onloadend = function() { // aqui um evento, que será disparado na primeira linha abaixo da função chamada
var image = new Image();
image.src = reader.result; // vai disparar o tratamento do evento abaixo
image.onload = function() {
var maxWidth = 800,
maxHeight = 600,
width = image.width,
height = image.height;
// calculate the width and height, constraining the proportions
if (width > height) {
if (width > maxWidth) {
//height *= max_width / width;
height = Math.round(height *= maxWidth / width);
width = maxWidth;
}
} else {
if (height > maxHeight) {
//width *= max_height / height;
width = Math.round(width *= maxHeight / height);
height = maxHeight;
}
}
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, maxWidth, maxHeight);
// The resized file ready for upload
var finalFile = canvas.toDataURL("image/jpeg",0.8); //a 80% de qualidade
// aqui cria-se novo input comun!
/*var newinput = document.createElement("input");
newinput.type = 'text';
newinput.name = "edt" & Elemento;
newinput.value = finalFile; // put result from canvas into new hidden input
form.appendChild(newinput);*/
document.getElementById("edtArq_1").value = finalFile;
var preview = document.getElementById('preview');
//alert(preview.id);
preview.appendChild(canvas); // do the actual resized preview
}
}
}
</script>
<html>
<form id="form" action="submit" method="post" accept-charset="utf-8" enctype="multipart/form-data">
<!-- this will be left behind - we don't want to upload Mbytes of information -->
<input type='file' name='Arq_1' id='Arq_1' size='50' onchange='Compactar("Arq_1");'>
<form method="POST" id='frmFotos' action='SalvaArquivo.asp'>
<!-- this could be a hidden element -->
<input name='edtArq_1' id='edtArq_1'><br>
<input type='submit' name ='cmdEnviar' id='cmdEnviar' value='Enviar' >
</form>
<!-- just for you see the new resized image - no upload too -->
<div id="preview"></div>
</html>
The page that will reveive the request from the first page and save the image:
<html>
<!-- by arturmariojr@gmail.com - on december/2012 -->
<!-- this script could be avoided if I had put the img element in the page directly
. By the way, actualyy there's no necessity of showing nothing to user
-->
<script language='JavaScript'>
var newImg = document.createElement("img");
newImg.src = '<%=request.form("edtArq_1")%>';
document.body.appendChild(newImg);
</script>
<body>
<input name='edtOriginal' value='<%=request.form("edtArq_1")%>'>
<%
' the data is encoded, so, we will need to deencode it ...
Function Base64Decode(ByVal base64String)
'rfc1521
'1999 Antonin Foller, Motobit Software, http://Motobit.cz
Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
Dim dataLength, sOut, groupBegin
'remove white spaces, If any
base64String = Replace(base64String, vbCrLf, "")
base64String = Replace(base64String, vbTab, "")
base64String = Replace(base64String, " ", "")
'The source must consists from groups with Len of 4 chars
dataLength = Len(base64String)
If dataLength Mod 4 <> 0 Then
Err.Raise 1, "Base64Decode", "Bad Base64 string."
Exit Function
End If
' Now decode each group:
For groupBegin = 1 To dataLength Step 4
Dim numDataBytes, CharCounter, thisChar, thisData, nGroup, pOut
' Each data group encodes up To 3 actual bytes.
numDataBytes = 3
nGroup = 0
For CharCounter = 0 To 3
' Convert each character into 6 bits of data, And add it To
' an integer For temporary storage. If a character is a '=', there
' is one fewer data byte. (There can only be a maximum of 2 '=' In
' the whole string.)
thisChar = Mid(base64String, groupBegin + CharCounter, 1)
If thisChar = "=" Then
numDataBytes = numDataBytes - 1
thisData = 0
Else
thisData = InStr(1, Base64, thisChar, vbBinaryCompare) - 1
End If
If thisData = -1 Then
Err.Raise 2, "Base64Decode", "Bad character In Base64 string."
Exit Function
End If
nGroup = 64 * nGroup + thisData
Next
'Hex splits the long To 6 groups with 4 bits
nGroup = Hex(nGroup)
'Add leading zeros
nGroup = String(6 - Len(nGroup), "0") & nGroup
'Convert the 3 byte hex integer (6 chars) To 3 characters
pOut = Chr(CByte("&H" & Mid(nGroup, 1, 2))) + _
Chr(CByte("&H" & Mid(nGroup, 3, 2))) + _
Chr(CByte("&H" & Mid(nGroup, 5, 2)))
'add numDataBytes characters To out string
sOut = sOut & Left(pOut, numDataBytes)
Next
Base64Decode = sOut
End Function
' now, we will save the data (new image) using the old FileSystemObject !!!
Set fso = Server.CreateObject ("Scripting.FileSystemObject")
If Err.Number <> 0 Then
Response.write "Não foi possível instanciar objeto fso!<br>" & Err.description
response.end
End if
dim Caminho, objArq
Caminho = Server.MapPath("./images") 'where I saved the new image
response.write Caminho
If Err.Number <> 0 Then
Response.write "Não foi possível localizar caminho! " & Caminho & "<br>" & Err.description & "<br>"
else
Set oFile = fso.CreateTextFile(Caminho & "\Teste.jpg", true)
oFile.Write Base64Decode(replace(request.form("edtArq_1"), "data:image/jpeg;base64,", "")) 'BinaryToString(request.from("edtArq_1"))
If Err.Number <> 0 Then
Response.write "Não foi possível localizar thum(s)!" & Caminho & "<br>" & Err.description & "<br>"
end if
oFile.close
end if
%>
</body>
</html>
精彩评论