图片(画布上的图片)上传总结

最近在做图片上传的一些东西,目前为止已经做的相对比较完善了,所以对图片上传做一些总结。

我最初的想法是把html5的标签canvas上的图片得到,上传到服务器上并能够及时预览。

canvas上的图片分为两种情况:

1.自己绘制上去的。代码如下:

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var grd=cxt.createLinearGradient(0,0,175,50);
grd.addColorStop(0,"#FF0000");
grd.addColorStop(1,"#00FF00");
cxt.fillStyle=grd;
cxt.fillRect(0,0,175,50);

2.选择本地的一幅图片放置在画布上。代码入下:

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="flower.png"
cxt.drawImage(img,0,0);

但是canvas上自己绘制的图片往后台传比较容易,但是第2种情况本地img的src获取不到(这是浏览器为了安全考虑不让用户获取到的),因此也就无法将img放置在画布上。

因此我就使用普通的<img>标签来保存选择的本地图片,用<canvas>来保存自己绘制的图片。

html代码片段:

<td>

<!--这个button是用来消除input type=‘file‘的默认样式,将其隐藏起来,然后用trigger()来触发输入框的事件-->
        <button id="choosePicBtn" disabled=true onclick="trigger()">选择图片</button>
        <input type="file" hidden="true" name="picFile" id="fileChoose" onchange="drawPicLogo()" accept="image/png,image/jpg,image/jpeg"/>
</td>

....

<!--这个区域是用来预览图片的,不论是自己绘制的还是本地选择的一幅图片-->

<td colspan=2 id="picArea">
</td>

/*
* hjw 文件选择事件函数
*/
function trigger() {
    $("#fileChoose").click();
}

如果我选择的是自己绘制图片,那么就执行下面语句:

$("#picArea").html("<canvas id=‘logoCanvas‘ width=‘512‘ height=‘64‘></canvas>");如果是选择已有的图片,那么就执行下面的语句:
$("#picArea").html("<img id=‘logoImg‘ width=‘512‘ height=‘64‘></img> ");并设置img的url,取得图片的url函数如下:
//获取input[file]图片的url Importantfunction getFileUrl(fileId) {    var url;    var file = Id(fileId);   var agent = navigator.userAgent;   if (agent.indexOf("MSIE")>=1) {   url = file.value;    } else if(agent.indexOf("Firefox")>0) {    url = window.URL.createObjectURL(file.files.item(0));    } else if(agent.indexOf("Chrome")>0) {   url = window.URL.createObjectURL(file.files.item(0));    }    return url; } 开始上传:,首先是自己绘制的图片,
/* * hjw * 将canvas上的对象保存为图片,并上传 * */function textLogoUpload(logoTitle,font,fontSize,txtColor,backGroundColor,showState,isBKGColor){   //选择的输入源   var selectedNode=zTree.getSelectedNodes()[0];   var id=selectedNode.id;   //文字台标的位置信息,x坐标和y坐标   var xPos=$("#logo_x_value").val();   var yPos=$("#logo_y_value").val();   var channel=selectedNode.channel;   var subChannel=selectedNode.subChannel;   var canvas = document.getElementById("logoCanvas");   var data=canvas.toDataURL();   //dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了   data=data.split(",")[1];    var  dataImg={       file:data,//文字台标的图片数据(BASE64编码)       id:id,      showState:showState,       logoText:logoTitle,       font:font,       fontSize:fontSize,       txtColor:txtColor,       backGroundColor:backGroundColor,       x:xPos,       y:yPos,      channel:channel,      subChannel:subChannel,      isBKGColor:isBKGColor    };   $.ajax({       url:‘/darwin/service/imgUpload/textLogo‘,       type:"POST",       data:dataImg,       success:function(){       }   });}后台,
@RequestMapping(value="textLogo", method = RequestMethod.POST)public void  textLogoUpload(HttpServletRequest request, HttpServletResponse response){
//首先将前台传递过来的BASE64字符串解码为图片File file=decodeBase64ToFile(request.getParameter("file"));....................
}Base64解码的类如下:
package darwin.soc.videowallcontroller.web.imgUpload;

/** * Created by seven_hu on 2015/9/8. */public class BASE64Code {    /**     * Base64编码表。     */    private static final char[] BASE64CODE =            {‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘, ‘H‘, ‘I‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘, ‘N‘, ‘O‘, ‘P‘, ‘Q‘, ‘R‘, ‘S‘, ‘T‘, ‘U‘, ‘V‘,                    ‘W‘, ‘X‘, ‘Y‘, ‘Z‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘, ‘h‘, ‘i‘, ‘j‘, ‘k‘, ‘l‘, ‘m‘, ‘n‘, ‘o‘, ‘p‘, ‘q‘,                    ‘r‘, ‘s‘, ‘t‘, ‘u‘, ‘v‘, ‘w‘, ‘x‘, ‘y‘, ‘z‘, ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘+‘, ‘/‘,};

    /**     * Base64解码表。     */    private static final byte[] BASE64DECODE =            {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,                    -1, -1, -1,                    -1,                    -1, // 注意两个63,为兼容SMP,                    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 63,                    -1,                    63, // “/”和“-”都翻译成63。                    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,                    12, 13,                    14, // 注意两个0:                    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1,                    -1, // “A”和“=”都翻译成0。                    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,                    -1, -1, -1, -1, -1,};

    private static final int HEX_255 = 0x0000ff;

    private static final int HEX_16515072 = 0xfc0000;

    private static final int HEX_258048 = 0x3f000;

    private static final int HEX_4032 = 0xfc0;

    private static final int HEX_63 = 0x3f;

    private static final int HEX_16711680 = 0xff0000;

    private static final int HEX_65280 = 0x00ff00;

    private static final int NUMBER_TWO = 2;

    private static final int NUMBER_THREE = 3;

    private static final int NUMBER_FOUR = 4;

    private static final int NUMBER_SIX = 6;

    private static final int NUMBER_EIGHT = 8;

    private static final int NUMBER_TWELVE = 12;

    private static final int NUMBER_SIXTEEN = 16;

    private static final int NUMBER_EIGHTEEN = 18;

    /**     * 构造方法私有化,防止实例化。     */    private BASE64Code()    {    }

    /**     * Base64编码。将字节数组中字节3个一组编码成4个可见字符。     *     * @param b     *            需要被编码的字节数据。     * @return 编码后的Base64字符串。     */    public static String encode(byte[] b)    {        int code = 0;

        // 按实际编码后长度开辟内存,加快速度        StringBuffer sb = new StringBuffer(((b.length - 1) / NUMBER_THREE) << NUMBER_TWO + NUMBER_FOUR);

        // 进行编码        for (int i = 0; i < b.length; i++)        {            code |=                    (b[i] << (NUMBER_SIXTEEN - i % NUMBER_THREE * NUMBER_EIGHT))                            & (HEX_255 << (NUMBER_SIXTEEN - i % NUMBER_THREE * NUMBER_EIGHT));            if (i % NUMBER_THREE == NUMBER_TWO || i == b.length - 1)            {                sb.append(BASE64CODE[(code & HEX_16515072) >>> NUMBER_EIGHTEEN]);                sb.append(BASE64CODE[(code & HEX_258048) >>> NUMBER_TWELVE]);                sb.append(BASE64CODE[(code & HEX_4032) >>> NUMBER_SIX]);                sb.append(BASE64CODE[code & HEX_63]);                code = 0;            }        }

        // 对于长度非3的整数倍的字节数组,编码前先补0,编码后结尾处编码用=代替,        // =的个数和短缺的长度一致,以此来标识出数据实际长度        if (b.length % NUMBER_THREE > 0)        {            sb.setCharAt(sb.length() - 1, ‘=‘);        }        if (b.length % NUMBER_THREE == 1)        {            sb.setCharAt(sb.length() - NUMBER_TWO, ‘=‘);        }        return sb.toString();    }

    /**     * Base64解码。     *     * @param code     *            用Base64编码的ASCII字符串     * @return 解码后的字节数据     */    public static byte[] decode(String code)    {        // 检查参数合法性        if (code == null)        {            return null;        }        int len = code.length();        if (len % NUMBER_FOUR != 0)        {            throw new IllegalArgumentException("Base64 string length must be 4*n");        }        if (code.length() == 0)        {            return new byte[0];        }

        // 统计填充的等号个数        int pad = 0;        if (code.charAt(len - 1) == ‘=‘)        {            pad++;        }        if (code.charAt(len - NUMBER_TWO) == ‘=‘)        {            pad++;        }

        // 根据填充等号的个数来计算实际数据长度        int retLen = len / NUMBER_FOUR * NUMBER_THREE - pad;

        // 分配字节数组空间        byte[] ret = new byte[retLen];

        // 查表解码        char ch1, ch2, ch3, ch4;        int i;        for (i = 0; i < len; i += NUMBER_FOUR)        {            int j = i / NUMBER_FOUR * NUMBER_THREE;            ch1 = code.charAt(i);            ch2 = code.charAt(i + 1);            ch3 = code.charAt(i + NUMBER_TWO);            ch4 = code.charAt(i + NUMBER_THREE);            int tmp =                    (BASE64DECODE[ch1] << NUMBER_EIGHTEEN) | (BASE64DECODE[ch2] << NUMBER_TWELVE)                            | (BASE64DECODE[ch3] << NUMBER_SIX) | (BASE64DECODE[ch4]);            ret[j] = (byte)((tmp & HEX_16711680) >> NUMBER_SIXTEEN);            if (i < len - NUMBER_FOUR)            {                ret[j + 1] = (byte)((tmp & HEX_65280) >> NUMBER_EIGHT);                ret[j + NUMBER_TWO] = (byte)((tmp & HEX_255));

            }            else            {                if (j + 1 < retLen)                {                    ret[j + 1] = (byte)((tmp & HEX_65280) >> NUMBER_EIGHT);                }                if (j + NUMBER_TWO < retLen)                {                    ret[j + NUMBER_TWO] = (byte)((tmp & HEX_255));                }            }        }        return ret;    }}
然后开始选择图片的上传:前台
function picLogoUpload(showState,isBKGColor){   //获得设置台标的输入源      var selectedNode=zTree.getSelectedNodes()[0];      var id=selectedNode.id;      var channel=selectedNode.channel;      var subChannel=selectedNode.subChannel;      $.ajaxFileUpload({         url : ‘/darwin/service/imgUpload/picLogo‘, // 用于文件上传的服务器端请求地址         type : ‘post‘,         data: { id: id, channel: channel, subChannel: subChannel, showState: showState, isBKGColor: isBKGColor },         secureuri : false, // 一般设置为false         fileElementId : ‘fileChoose‘, // 文件上传空间的id属性 <input type="file"                                 // id="file" name="file" />         dataType : ‘text‘, // 返回值类型 一般设置为json         success : function(data, status) // 服务器成功响应处理函数         {         },         error : function(data, status, e)// 服务器响应失败处理函数         {         }      });      return false;}这里用到了 ajaxFileUpload.js插件,后台:
@RequestMapping(value = "picLogo", method = RequestMethod.POST)public void  picLogoUpload(@RequestParam("picFile") MultipartFile file,                     HttpServletRequest request, HttpServletResponse response)      throws Exception {........}
时间: 2024-10-06 16:47:50

图片(画布上的图片)上传总结的相关文章

HTML5 file API加canvas实现图片前端JS压缩并上传 (转载)

一.图片上传前端压缩的现实意义 对于大尺寸图片的上传,在前端进行压缩除了省流量外,最大的意义是极大的提高了用户体验. 这种体验包括两方面: 由于上传图片尺寸比较小,因此上传速度会比较快,交互会更加流畅,同时大大降低了网络异常导致上传失败风险. 最最重要的体验改进点:省略了图片的再加工成本.很多网站的图片上传功能都会对图片的大小进行限制,尤其是头像上传,限制5M或者2M以内是非常常见的.然后现在的数码设备拍摄功能都非常出众,一张原始图片超过2M几乎是标配,此时如果用户想把手机或相机中的某个得意图片

【图片】移动端图片上传旋转、压缩的解决方案

移动端图片上传旋转.压缩的解决方案 来源 知乎    作者 林鑫 工作上有手机上传准考证等图片的功能,这个是非常必要的,作者写的很全面,就直接记录这个地址了 还有一篇 文件的上传.下载

相册选择头像或者拍照 上传头像以NSData 图片二进制格式 表单上传

一.点击头像图片 或者按钮 在相册选择照片返回img,网络上传头像要用data表单上传 (1)上传头像属性 // 图片二进制格式 表单上传 @property (nonatomic, strong) NSData *imageWithData; (2)头像点击事件 - (void)headImageEvent{ NSLog(@"上传头像"); [self selectPhotoAlbumWithSelectPhotoHandle:^(UIImage *img) { self.heade

前端预览图片和H5canvas压缩图片上传

思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法得到base64字符串来实现压缩. 1.base64转二进制文件 /** * dataURL to blob, ref to https://gist.github.com/fupslot/5015897 * @param dataURI * @returns {Blob} */ function dataURItoBlob(dataURI) { var byteString = atob(dataURI.spl

移动端图片操作(一)——上传

上传我们一般都是用“input[type=file]”控件.当你用此控件时,你就授权了网页和服务器访问对应的文件,就可以得到File对象. 友情提示在,在Android手机webview中,是不支持上传文件的,网上说是修改Android端的代码,但我没试过,我们这边是使用客户端提供的接口来实现上传的. 下面的示例代码可以在这里查看到. 一.accept属性 该属性表明了服务器端可接受的文件类型,可以限制你手机选择相关的文件,如果限制多个,可以用逗号分割,下面的代码就表示只能选择图片与音频相关的文

ASP.NET MVC中使用Dropzone.js实现图片的批量拖拽上传

说在前面 最近在做一个MVC相册的网站(这里),需要批量上传照片功能,所以就在网上搜相关的插件,偶然机会发现Dropzone.js,试用了一下完全符合我的要求,而且样式挺满意的,于是就在我的项目中使用了这个插件.在使用的过程中发现中文的相关文档较少,说多了都是泪,硬着头皮看官方的网站,本来英文不咋地,只能边查单词边用了,于是就有了这篇文章,主要是总结在使用Dropzone中的遇到的一些问题及详细的使用步骤. Dropzone.js是啥? Dropzone.js是一个开源库,提供拖放文件上传及图像

ueditor .net版本上传不了图片问题

百度的Ueditor适合中国人,所以,选择了它,可是恶梦才刚刚开始,最头痛的就是图片死活就是上传不成功,悲剧中.. 现在来分析下为什么报错:什么也不说了,上图 ueditor .net版本上传不了图片问题

iOS12系统图片heic如何在电脑上查看

说到iOS12系统,只有iPhone用户应该比较熟悉些,对于安卓用户来说都会比较陌生的,而且其系统的图片格式也是比较独特的,在电脑上是无法直接查看的,那iOS12系统图片heic如何在电脑上查看呢? 1.在电脑上运行苹果HEIC图片转换器,可以将手机中的heic格式传到电脑中,如果较好的情况下,最好新建一个文件夹批量保存转换:2.打开转换器,需要先添加文件,即iPhone拍出来的照片,可以批量添加图片,点击"添加图片"即可添加:3.HEIC格式图片添加之后,点击输出目录后面的三个点按钮

【Android】读取sdcard上的图片

Android读取sdcard上的图片是很easy的事情,以下用一个样例来说明这个问题. 首先,在sdcard上有一张已经准备好的img25.jpg 以下,须要做的是把这张图片读取到app中显示. 做到例如以下的效果: 1.首先你要在AndroidManifest.xml申请读取sdcard的权限,增加一条语句之后,AndroidManifest.xml例如以下: <?xml version="1.0" encoding="utf-8"? > <m