1. 程式人生 > >Spring Boot筆記之上傳圖片(Base64和MultipartFile)

Spring Boot筆記之上傳圖片(Base64和MultipartFile)

SpringMVC接收圖片

圖片的上傳

form表單上傳

<form action="/user/upload/file" method="post" enctype="multipart/form-data">
    <input type="file"
name="img" />
<input type="submit" /> </form>

jquery.form.js提供的ajax上傳

function updateFile() {
    $('#file').ajaxSubmit({
      url: url,
      type: 'POST',
      //contentType: false,
      xhrFields: {
        withCredentials: true
      },
      crossDomain: true,
      success:
function (result) { }, error: function (result) { } }); }

Base64格式上傳

有些APP外掛會這麼幹,這裡就不寫了。

SpringMVC接收

MultipartFile接收

SpringMVC提供的org.springframework.web.multipart.MultipartFile很強大,接收file只需要@RequestParam(value = "img") MultipartFile file就可以了,MultipartFile還提供的幾個很好用的API:

  • 獲取檔案型別getContentType()
  • 獲取檔案大小getSize()
  • 儲存檔案transferTo(java.io.File file)

接收、校驗和儲存:

@Controller
@RequestMapping("/user")
public class UserController extends BaseController {
    private static Logger logger = LoggerFactory.getLogger(UserController.class);
    @Value(value = "${image.path:./img}")
    private String imagePath;

    @Value(value = "${image.host:http://localhost}")
    private String imageHost;

    @RequestMapping(value = "/upload/file", method = RequestMethod.POST)
    @ResponseBody
    public Result<String> saveFile(@RequestParam(value = "img") MultipartFile file) {
        StringBuffer fileName = new StringBuffer();
        fileName.append(UUID.randomUUID().toString().replaceAll("-", ""));
        String type = file.getContentType();
        if ("image/png".equals(type)) {
            fileName.append(".png");
        } else if ("image/jpeg".equals(type)) {
            fileName.append(".jpeg");
        } else if ("image/gif".equals(type)) {
            fileName.append(".gif");
        } else {
            return new Result.Builder<String>()
                    .code(-1)
                    .msg("請選擇.png.jpg格式的圖片")
                    .build();
        }
        if (file.getSize() > 1024000L) {
            return new Result.Builder<String>()
                    .code(-1)
                    .msg("圖片超過1Mb")
                    .build();
        }
        try {
            file.transferTo(new File(imagePath, fileName.toString()));
            return new Result.Builder<String>()
                    .code(0)
                    .msg("成功")
                    .data(imageHost + fileName.toString())
                    .build();
        } catch (IOException e) {
            e.printStackTrace();
            return new Result.Builder<String>()
                    .code(-1)
                    .msg("儲存失敗")
                    .build();
        }
    }
}

Base64字串接收

    @RequestMapping(value = "/upload/base64", method = RequestMethod.POST)
    @ResponseBody
    public Result<String> saveBase64(@RequestParam(value = "img") String base64Str) {
        StringBuffer fileName = new StringBuffer();
        fileName.append(UUID.randomUUID().toString().replaceAll("-", ""));
        if (StringUtils.isBlank(base64Str)) {
            return new Result.Builder<String>()
                    .code(-1)
                    .msg("file不可預設")
                    .build();
        } else if (base64Str.indexOf("data:image/png;") != -1) {
            base64Str = base64Str.replace("data:image/png;base64,", "");
            fileName.append(".png");
        } else if (base64Str.indexOf("data:image/jpeg;") != -1) {
            base64Str = base64Str.replace("data:image/jpeg;base64,", "");
            fileName.append(".jpeg");
        } else {
            return new Result.Builder<String>()
                    .code(-1)
                    .msg("請選擇.png.jpg格式的圖片")
                    .build();
        }
        File file = new File(imagePath, fileName.toString());
        byte[] fileBytes = Base64.getDecoder().decode(base64Str);
        try {
            FileUtils.writeByteArrayToFile(file, fileBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return new Result.Builder<String>()
                    .code(-1)
                    .msg("儲存失敗")
                    .build();
        }
        return new Result.Builder<String>()
                .code(0)
                .msg("成功")
                .data(imageHost + fileName.toString())
                .build();
    }

為了避免檔案重名、Linux檔案系統與Windows檔案系統差異等因素會引起的異常,我通常使用UUID重新命名後再儲存。

nginx配置

上面程式碼中的image.path是檔案的儲存路徑, image.host是提供給前端的訪問方式,具體配置要結合nginx代理的配置:

server {
	listen 80 default_server;
	listen [::]:80 default_server;
	root /data/www;
	……
}

這是一個本地測試環境的配置,僅供參考。image.path配置為/data/www/img/image.host配置為http://localhost/img/,這樣,圖片檔案會儲存在/data/www/img/,http訪問img/test.jpeg時,nginx就會響應這張圖片。