java實現圖片文件與Base64的互轉


通過form表單上傳圖片時,有時候web容器對文件大小的限制會影響我們上傳。這時,前端頁面可以考慮將圖片轉換成base64串來實現上傳。可參見:vue利用canvas將圖片上傳到服務器

 

■ 圖片與Base64的互轉,其實就是利用了文件流與Base64的互轉

 

> 文件轉換成Base64字符串:讀取文件的輸入流,因為文件流是字節流,所以要放到byte數組(字節數組,byte取值范圍-128~127)里,然后對byte數組做Base64編碼,返回字符串。

> Base64串轉換成文件:對Base64編碼的字符串進行Base64解碼,得到byte數組,利用文件輸出流將byte數據寫入到文件。

 

介紹一下byte:   

byte,即字節,就是我們常說的B(b)。byte由8位二進制組成,在java中,byte類型的數據是8位帶符號的二進制數。

在計算機中,8位帶符號二進制數的取值范圍是[10000000,01111111],其中高位(第一位)代表符號,0代表正數,1代表負數,10000000對應十進制-128,01111111對應十進制127,所以,byte的取值范圍是[-128,127]。

現在的文件比如手機拍攝的照片都比較大,幾乎不會談到B了,也很少談到K(kb)了,常見的是M(mb)。byte數組就是字節數組,byte[] buffer=new byte[1024]代表數組容量為1k。換算單位:1Mb = 1024kb, 1Kb=1024b。

 

Talk is cheap, show me the code。直接上代碼:

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.*;

public class ImageBase64Converter {
    /**
     * 本地文件(圖片、excel等)轉換成Base64字符串
     *
     * @param imgPath     
     */
    public static String convertFileToBase64(String imgPath) {
        byte[] data = null;
        // 讀取圖片字節數組
        try {
            InputStream in = new FileInputStream(imgPath);
            System.out.println("文件大小(字節)="+in.available());
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 對字節數組進行Base64編碼,得到Base64編碼的字符串
        BASE64Encoder encoder = new BASE64Encoder();
        String base64Str = encoder.encode(data);
        return base64Str;
    }

    /**
     * 將base64字符串,生成文件
     */
    public static File convertBase64ToFile(String fileBase64String, String filePath, String fileName) {

        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && dir.isDirectory()) {//判斷文件目錄是否存在
                dir.mkdirs();
            }

            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bfile = decoder.decodeBuffer(fileBase64String);

            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bfile);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

}

 

testcase:

public static void main(String[] args) {
        long start = System.currentTimeMillis();
        String imgBase64Str= ImageBase64Converter.convertFileToBase64("D:\\Pictures\\科技\\liziqi-李子柒爆紅.jpg");
//        System.out.println("本地圖片轉換Base64:" + imgBase64Str);
        System.out.println("Base64字符串length="+imgBase64Str.length());
        ImageBase64Converter.convertBase64ToFile(imgBase64Str,"D:\\Pictures\\科技","test.jpg");
        System.out.println("duration:"+(System.currentTimeMillis()-start));

        start=System.currentTimeMillis();
        String fileBase64Str= ImageBase64Converter.convertFileToBase64("D:\\Pictures\\科技\\PayOrderList200109075516581.xlsx");
//        System.out.println("本地excel轉換Base64:" + fileBase64Str);
        System.out.println("Base64字符串length="+fileBase64Str.length());
        ImageBase64Converter.convertBase64ToFile(fileBase64Str,"D:\\Pictures\\科技","test.xlsx");
        System.out.println("duration:"+(System.currentTimeMillis()-start));

    }

 

執行結果:

文件大小(字節)=2820811
Base64字符串length=3860058
duration:244
文件大小(字節)=25506
Base64字符串length=34902
duration:10

 

 

提醒一下:獲取文件的大小是用FileInputStream實例的available()方法哦,用File實例的length()返回的是0。

如下圖,測試方法里圖片文件“liziqi-李子柒爆紅.jpg”的大小正是2820811字節   ÷1024=2755KB  ÷1024=2.68M

 

 

■ Fastdfs工具類中的圖片上傳

FastdfsClientUtil中關於圖片上傳,有3個重載方法。

  • public String uploadImageAndCrtThumbImage(MultipartFile myfile) throws Exception
  • public String uploadImageAndCrtThumbImageByStream(InputStream inputStream,int size,String fileExtName) throws Exception
  • public String uploadImageAndCrtThumbImageByBase64(String base64ImgData) throws Exception

在這里,我說一下uploadImageAndCrtThumbImageByBase64這個方法。它的入參是一個base64串。注意這個這個參數的值,在base64串的前頭有一個前綴,諸如 "data:image/gif;base64,"、"data:image/jpeg;base64,"。其中gif、jpeg是目標圖片文件的擴展名。這正適合於前端頁面通過base64串來上傳圖片的場景。

下面貼出來這個方法的實現,一看便知。

import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

@Component
public class FastdfsClientUtil {

   private final Logger logger = LoggerFactory.getLogger(FastdfsClientUtil.class);
   @Autowired
   private FastFileStorageClient storageClient;

   //上傳文件並生成縮略圖
   public String uploadImageAndCrtThumbImageByBase64(String base64ImgData) throws Exception {

      BASE64Decoder decoder = new BASE64Decoder();
      String[] base64ImageSplit = base64ImgData.split(",");
      byte[] result = decoder.decodeBuffer(base64ImageSplit[1]);//解碼
      String fileExtName = base64ImageSplit[0].substring(base64ImageSplit[0].indexOf("/")+1,base64ImageSplit[0].indexOf(";"));
      for (int i = 0; i < result.length; ++i) {
         if (result[i] < 0) {// 調整異常數據
            result[i] += 256;
         }
      }
      InputStream inputStream  = new ByteArrayInputStream(result);
      return uploadImageAndCrtThumbImageByStream(inputStream, result.length,fileExtName );
   }

}

 

測試用例:

    @Test
    public void uploadPng() throws Exception {

        String imgBase64="/9j/4AAQSkZJRgABAQEAYABgAAD/7QjCUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA\n" +
                "AgBIAAAAAQACOEJJTQQNAAAAAAAEAAAAHjhCSU0EGQAAAAAABAAAAB44QklNA/MAAAAAAAkAAAAA\n" +
                "AAAAAAEAOEJJTQQKAAAAAAABAAA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9m\n" +
                "ZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAAB\n" +
                "AC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA////\n" +
                "/////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////\n" +
                ......
                "0HoaKACg80GjvQISijrmjFMD/9k=";
        String fileName = fastdfsClientUtil.uploadImageAndCrtThumbImageByBase64("data:image/png;base64,"+imgBase64);
        System.out.println("------------" + fileName);
        //fileName:上傳后的文件(含路徑):group1/M00/00/20/wKgoVF8hHdSAaRrkAAAlClwx2Hg883.png
        //訪問:http://192.168.40.84:8888/group1/M00/00/20/wKgoVF8hHdSAaRrkAAAlClwx2Hg883.png

    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM