微网站头像上传

本人使用过以下几种方式(jfinal+light7):
一、页面

这里的div之前是image,由于图片显示会被拉伸,所以换成了背景图来实现;class='fileopa'这个是让input的作用域扩大至image范围;
<div class="thumbavatar border" id="my_personal_titleimg" >
      <!-- <form name="uploadForm" id="uploadForm" enctype="multipart/form-data" action="/muser/imageUpload" method="post"> -->
       <input id="my_personal_file_id" class="fileopa" name="my_personal_file"    type="file" accept="image/*" capture="camera" />
    <!-- </form>  -->
</div>

二、js

1、通过jq的ajaxFileUpload上传

$.ajaxFileUpload({  
        url:'/muser/imageUpload',
        type: "POST",
        async : false, 
        secureuri:false,  
        fileElementId:'my_personal_file_id',
        dataType: 'JSON',//返回数据的类型
        success: function (data) {  
            //把图片替换 
            var obj = $.parseJSON($(data).text());
            if(obj.resultcode=="10000"){
                var url=obj.path;
                $('#my_personal_titleimg').attr("src",imgPath+url); //个人中心头像
                location.href="/muser/personal";
            }else{
                $.alert(obj.message);
            }
        },  
        error: function (data, status, e) {  
             $.hideIndicator();
             $.alert("头像上传失败!");
        } 
    });

2、通过jq的ajaxsubmit上传

$("#uploadForm").ajaxSubmit({
        dataType: 'json',
        success:function(result,status){
            if(result.success){
                var url=result.path;
                $('#my_personal_titleimg').attr("src",imgPath+url); //个人中心头像
                //location.href="/muser/personal";
                $.hideIndicator();
            }else{
                $.alert(result.message);
            }
        },
        error: function(result,status,e){ 
            $.hideIndicator();
            $.alert("头像上传失败!");
        }
    });

以上的两种方式在本地测试时没问题的,但发现放在微信公众号上图片大小被限制上传。后面找资料发现了将文件base64再上传的方案。

3、通过js中的FileReader读取本地文件

    var img = document.getElementById("my_personal_file_id");
    var imgFile = new FileReader();  
    imgFile.readAsDataURL(img.files[0]);  
    imgFile.onload = function (e) {  
       var imgData = e.target.result; //base64数据    
       //$('#my_personal_titleimg').attr("src",imgData); //个人中心头像
       var submitData={base64_string:imgData};
       console.log(submitData);
       $.ajax({
           type: "POST",
           url: "/muser/imageUpload",
           data: submitData,
           dataType:"json",
           success: function(data){
               //var obj = $.parseJSON($(data).text());
                if(data.resultcode=="10000"){
                    var url=data.path;
                    $('#my_personal_titleimg').attr("src",imgPath+url); //个人中心头像
                    location.href="/muser/personal";
                }else{
                    $.alert(data.message);
                }
           },
            error:function(XMLHttpRequest, textStatus, errorThrown){ //上传失败 
               $.alert("头像上传失败!");
            }
        }); 

但这个方法有浏览器的兼容性问题,尤其是放在微信公众号里。

4、通过localResizeIMG插件来实现

$('#my_personal_file_id').localResizeIMG({
          width: 400,
          quality: 1,
          success: function (result) {  
              var submitData={
                    base64_string:result.base64 //rst.base64  clearBase64
                }; 
            $.ajax({
               type: "POST",
               url: "/muser/imageUpload",
               data: submitData,
               dataType:"json",
               success: function(data){
                   //var obj = $.parseJSON($(data).text());
                    if(data.resultcode=="10000"){
                        var url=data.path;
                        $('#my_personal_titleimg').attr("src",imgPath+url); //个人中心头像
                        location.href="/muser/personal";
                    }else{
                        $.alert(data.message);
                    }
               }, 
                complete :function(XMLHttpRequest, textStatus){
                },
                error:function(XMLHttpRequest, textStatus, errorThrown){ //上传失败 
//                 alert(XMLHttpRequest.status);
//                 alert(XMLHttpRequest.readyState);
//                 alert(textStatus);
                }
            }); 
          }
      });

第三种和第四种都是上传base64再通过后台解码来实现图片文件上传的,目前最后一种在微信公众号里没什么问题。

三、后台

前两种就是传流保存再做其它压缩等操作即可,后两种就是需要将base64解码保存再做其它压缩等操作(当然还有业务逻辑)。这里面遇到过几个莫名其妙的问题和大家分享下:
1、在有base64串生成图片文件的时候发现图片生成有问题,后来发现服务器端接收的字符串会把“+”替换成空格,加号(+)是BASE64编码的一部分。处理办法是:把空格替换成“+”,然后解码。
2、iphone手机会把拍照的图片旋转,这个需要exif来处理。有一点metadata-extractor-2.9.1.jar这个jar包低版本的不行,好像要2.8以上。还有就是无法获取base64中的图片方向信息(这个问题还没解决)。
贴下我后台代码吧:
1、controller

public void imageUpload()
    {
        JSONObject result = new JSONObject();// 返回json

        if (isLogin())
        {
            try
            {
                String sourcePath = ImageUtil.getPath(".jpg");
                String targetPath = ImageUtil.getPath(".jpg");// 获取要存放的目标图片路径
                String staticPath = String.valueOf(PropertiesPlugin.getParamMapValue(DictKeys.statics_res_path)).replace("\\","/");
                String targetPathTemp = targetPath.replace(staticPath, "");// 获取返回给页面图片的路径
                // 获得一个图片文件流,我这里是从flex中传过来的
                String imgdata = getPara("base64_string").split(",")[1];
                imgdata = imgdata.replace(" ", "+");
                ImageUtil.generateImage(imgdata,sourcePath);
                ImageUtil.resizeFix(sourcePath, targetPath, 400, 400);// 压缩图片并保存至目标图片路径

                User user = getCUser();
                UserInfo userInfo = new UserInfo();
                userInfo.set("ids", user.getStr("userinfoids"));
                userInfo.set("titleimg", targetPathTemp);
                UserService.service.updateUserInfo(userInfo, user.getStr("ids"), getRequest());// 更新头像

                ImageUtil.delete(sourcePath); // 删除原始图片
                result.put("path",  targetPathTemp);
                returnResult(result, AppResult.common_success, "上传成功");
            }
            catch (Exception e)
            {
                returnResult(result, AppResult.common_fail, "上传失败,请重新上传");
                renderJson(result);
            }
        }
        else
        {
            returnResult(result, AppResult.common_fail, "未登录,请先登录");
        }

        renderJson(result);
    }

2、ImageUtil

    public static void generateImage(String imgStr, String imgFilePath) throws IOException, ImageProcessingException
    {
        BASE64Decoder decoder = new BASE64Decoder();
        OutputStream out = null;
        byte[] bytesTemp = null;

        try
        {
            byte[] bytes = decoder.decodeBuffer(imgStr);// Base64解码
            for (int i = 0; i < bytes.length; ++i)
            {
                if (bytes[i] < 0)
                {
                    bytes[i] += 256;// 调整异常数据
                }
            }

            InputStream is = new ByteArrayInputStream(bytes);
            Metadata metadata = ImageMetadataReader.readMetadata(is);
            Directory exif = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);

            if (exif != null)
            {
                String type = exif.getString(40961);// 由于方向变量找不到,就随便弄个,相当于安卓不旋转,ios旋转
                if (StringUtils.isNotBlank(type))
                {
                    switch (Integer.parseInt(type))
                    {
                        case 2://要进行180度旋转
                            bytesTemp = rotateImage(bytes , 180.0 , "jpg");
                            break;
                        case 1://要进行90度旋转
                            bytesTemp = rotateImage(bytes , 90.0 , "jpg");
                            break;
                        case 3://要进行-90度旋转
                            bytesTemp = rotateImage(bytes , -90.0 , "jpg");
                            break;
                        default:
                            bytesTemp = bytes;
                    }
                }
                else
                {
                    bytesTemp = bytes;
                }
            }
            else
            {
                bytesTemp = bytes;
            }

            makeDirs(imgFilePath);
            out = new FileOutputStream(new File(imgFilePath));
            out.write(bytesTemp);
        }
        finally
        {
            if(out != null)
            {
                out.close();
            }
        }
    }

    public static byte[] rotateImage(byte[] bytes , double angle , String format) throws IOException
    {
        ByteArrayOutputStream baos = null;
        try
        {
            InputStream input = new ByteArrayInputStream(bytes);
            BufferedImage oldImage = ImageIO.read(input);
            int width = oldImage.getWidth();
            int height = oldImage.getHeight();
            double[][] newPositions = new double[4][];
            newPositions[0] = calculatePosition(0, 0, angle);
            newPositions[1] = calculatePosition(width, 0, angle);
            newPositions[2] = calculatePosition(0, height, angle);
            newPositions[3] = calculatePosition(width, height, angle);
            double minX = Math.min(Math.min(newPositions[0][0], newPositions[1][0]),Math.min(newPositions[2][0], newPositions[3][0]));
            double maxX = Math.max(Math.max(newPositions[0][0], newPositions[1][0]),Math.max(newPositions[2][0], newPositions[3][0]));
            double minY = Math.min(Math.min(newPositions[0][1], newPositions[1][1]),Math.min(newPositions[2][1], newPositions[3][1]));
            double maxY = Math.max(Math.max(newPositions[0][1], newPositions[1][1]),Math.max(newPositions[2][1], newPositions[3][1]));
            int newWidth = (int)Math.round(maxX - minX);
            int newHeight = (int)Math.round(maxY - minY);

            BufferedImage newImage = new BufferedImage(newWidth, newHeight , BufferedImage.TYPE_INT_BGR);

            Graphics2D g = newImage.createGraphics();

            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            double w = newWidth / 2.0;
            double h = newHeight / 2.0;

            g.rotate(Math.toRadians(angle), w, h);
            int centerX = (int)Math.round((newWidth - width) / 2.0);
            int centerY = (int)Math.round((newHeight - height) / 2.0);

            g.drawImage(oldImage, centerX, centerY, null);
            g.dispose();
            baos = new ByteArrayOutputStream();
            ImageIO.write(newImage, format, baos);// 利用ImageIO类的write方法,将BufferedImage以png图片的数据模式写入流。
            return baos.toByteArray();
        }
        finally
        {
            if(baos != null)
            {
                baos.close();
            }
        }
    }

    private static double[] calculatePosition(double x, double y, double angle)
    {
        angle = Math.toRadians(angle);
        double nx = (Math.cos(angle) * x) - (Math.sin(angle) * y);
        double ny = (Math.sin(angle) * x) + (Math.cos(angle) * y);
        return new double[] {nx, ny};
    }

    public static void resize(String sourcePath, String targetPath, int width, int height) throws IOException
    {
        FileOutputStream out = null;
        try
        {
            Image img = ImageIO.read(new File(sourcePath));// Image对象
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 生成缩略图片
            image.getGraphics().drawImage(img, 0, 0, width, height, null);// 绘制缩小后的图
            out = new FileOutputStream(new File(targetPath));// 输出到文件流  
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);  
            encoder.encode(image);
        }
        finally
        {
            if(out != null)
            {
                out.close();
            }
        }
    }

    public static void resizeFix(String sourcePath, String targetPath, int width, int height) throws IOException
    {
        File file = new File(sourcePath);// 读入文件
        Image img = ImageIO.read(file);// 构造Image对象
        int imgWidth = img.getWidth(null);// 得到源图宽
        int imgHeight = img.getHeight(null);// 得到源图长

        if (imgWidth / imgHeight > width / height)
        {
            resizeByWidth(sourcePath, targetPath, width);
        }
        else
        {
            resizeByHeight(sourcePath, targetPath, height);
        }
    }

    public static void resizeByWidth(String sourcePath, String targetPath, int width) throws IOException
    {
        File file = new File(sourcePath);// 读入文件
        Image img = ImageIO.read(file);// 构造Image对象
        int imgWidth = img.getWidth(null);// 得到源图宽
        int imgHeight = img.getHeight(null);// 得到源图长

        int height = (int) (imgHeight * width / imgWidth);
        resize(sourcePath, targetPath, width, height);
    }

    public static void resizeByHeight(String sourcePath, String targetPath, int height) throws IOException
    {
        File file = new File(sourcePath);// 读入文件
        Image img = ImageIO.read(file);// 构造Image对象
        int imgWidth = img.getWidth(null);// 得到源图宽
        int imgHeight = img.getHeight(null);// 得到源图长

        int width = (int) (imgWidth * height / imgHeight);  
        resize(sourcePath, targetPath, width, height); 
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值