JavaWeb圖片上傳的幾種方式


一、圖片上傳介紹

JavaWeb方向編程過程中,實現圖片上傳有三種方式:

1、傳統的基於springMVC的MultipartFile類實現圖片上傳。

2、基於Ajax的圖片上傳。

3、基於Base64壓縮的圖片上傳。

二、springMVC圖片上傳(springboot通用)

此方法的優點是可以將圖片和其他的表單元素一起提交到服務器,服務器接受到的圖片其實已經存儲於容器的臨時文件中,進行文件拷貝工作比較簡單。

缺點是無法及時看到圖片上傳的預覽效果,圖片一旦選擇錯誤只能重新提交。

注:紅色代碼為關鍵代碼。

1、頁面代碼

<form action="/upload" method="post" enctype="multipart/form-data">
    選擇頭像:<input type="file" name="file" accept="image/*" /> <br>
    用戶名字:<input type="text" name="userName"/> <br>
    <input type="submit" value="提交">
</form>

2、config.properties配置文件

創建名為config.properties的配置文件,並且再其中配置圖片上傳物理路徑。注意window和linux的寫法不同。

**此配置內容在springboot結構中的application.properties文件中配置**

file.location.path=d:/upload

3、spring-servlet.xml配置文件 

**此配置文件在springboot中不需要配置 - “習慣大於配置”**

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!-- 設置使用注解的類所在的jar包 -->
    <context:component-scan base-package="org.lanqiao.service"/>
    <context:component-scan base-package="org.lanqiao.controller"/>
    <!--讀取屬性文件-->
    <context:property-placeholder location="classpath:config.properties" ignore-unresolvable="true"/>
    <!-- 注冊HandlerMapping和HandlerAdapter組件 -->
    <mvc:annotation-driven/>
    <!-- 對靜態資源文件的訪問 支持訪問WEB-INF目錄 -->
    <mvc:default-servlet-handler/>
    <!-- 對轉向頁面的路徑解析。prefix:前綴,suffix:后綴 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
            p:prefix="/" p:suffix=".jsp"/>
    <!--文件上傳-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="104857600"/>
        <property name="maxInMemorySize" value="4096"/>
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>
</beans>

4、controller代碼

若是一次上傳多個文件,需要使用注解@RequestParam("inputName") 指明該文件對應表單中的input標簽的name屬性。如果name都是同名的,可以使用MultipartFile [] 文件數組來接收

@Controller
public class UserController {
    @Autowired
    UserService userService;
    @Value("${file.location.path}")
    private String fileLocation;
    @RequestMapping("/insert")
    public String insert(User user, MultipartFile file){
        String uri = FileUpload.upload(file,"/upload",fileLocation);
        user.setFacePic(uri);
        int ret = userService.insertUser(user);
        if(ret > 0 ){
            return "redirect:/get";
        }else{
            return "register";
        }
    }
}

5、上傳工具類代碼

public class FileUpload {
    /**
     * @param file 上傳的文件
     * @param path 文件的虛擬路徑,例如 /upload
     * @param fileLocation 文件的物理路徑,例如d:/upload
     * @return 文件的虛擬路徑+文件名
     *
     * fileName.lastIndexOf(".")為獲取后綴名
     * UUID.randomUUID()為獲取唯一標識,保證文件的唯一性
     */
    public static String upload(MultipartFile file, String path, String fileLocation) {
        String fileFinishName = null;
        try {
            // 如果目錄不存在則創建
            File uploadDir = new File(fileLocation);
            if (!uploadDir.exists()) {
                uploadDir.mkdir();
            }
            //獲取源文件名稱
            String fileName = file.getOriginalFilename();
            fileFinishName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."), fileName.length());
            //上傳文件到指定目錄下
            File uploadFile = new File(uploadDir + uploadDir.separator + fileFinishName);
            file.transferTo(uploadFile);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return path + "/" + fileFinishName;
    }
}

三、基於Ajax的圖片上傳

這種方式同第一種方式一樣都是使用multipart/form-data方式上傳,服務器端同樣使用springMVC(springboot)實現所以只有頁面代碼不一致,其他代碼(2、3、4、5)同上。

該方式前端使用的是jQuery的jquery.fileupload.js插件來實現。詳見大神文章:https://blog.csdn.net/qq_37936542/article/details/79258158

1、頁面先一用jQuery的插件

**順序不能錯誤**

<script src="js/jquery-3.2.1.min.js"></script>
<!-- jquery file upload相關js -->
<script src="js/jquery.ui.widget.js"></script>
<script src="js/jquery.iframe-transport.js"></script>
<script src="js/jquery.fileupload.js"></script>
<script src="js/jquery.fileupload-process.js"></script>
<script src="js/jquery.fileupload-validate.js"></script>

2、HTML代碼編寫

**不需要form標簽**

<style>
/* input樣式 */
#uploadImg{
display: none;
}
 
/* button樣式 */
#chooseFile{
background: #93b6fc;
}
 
#uploadFile,#rechooseFile {
display: none;
background: #93b6fc;
}
 
#image{
  width:200px;
  height:200px;
}
 
/* 進度條樣式 */
.bar { 
 background-image: -webkit-linear-gradient(top,#5cb85c 0,#449d44 100%); 
 background-image: -o-linear-gradient(top,#5cb85c 0,#449d44 100%); 
 background-image: -webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44)); 
 background-image: linear-gradient(to bottom,#5cb85c 0,#449d44 100%); 
 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 
 background-repeat: repeat-x; 
 height: 20px; 
 line-height: 20px; 
 -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.15); 
 box-shadow: inset 0 -1px 0 rgba(0,0,0,.15); 
 -webkit-transition: width .6s ease; 
 -o-transition: width .6s ease; 
 transition: width .6s ease; 
}
#progress { 
 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 
 background-repeat: repeat-x; 
 height: 20px; 
 width: 0%; 
 margin-bottom: 20px; 
 overflow: hidden; 
 background-color: #f5f5f5; 
 border-radius: 4px; 
 -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 
 box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 
 margin-top: 20px; 
}
</style>
<body>
    <div class="jquery-fileupload">
        <div class="">
            <input id="uploadImg" type="file" name="uploadImg" multiple style="display: none" /> 
                <button id="chooseFile">+選擇文件</button> 
                <button id="uploadFile">~開始上傳</button>
                <button id="rechooseFile">+重新選擇</button>
        </div>
        <div>
            <img id="image" src="">
        </div>
        <div id="progress">
            <div class="bar" style="width: 0%;"></div>
        </div>
    </div>
</body

3、js代碼

$(function() {
        $("#chooseFile").on("click", function() {
            $("#uploadImg").click();
        });
 
        $('#uploadImg').fileupload({
            url : '/upload',//請求發送的目標地址
            Type : 'POST',//請求方式 ,可以選擇POST,PUT或者PATCH,默認POST
            //dataType : 'json',//服務器返回的數據類型
            autoUpload : false,
            acceptFileTypes : /(gif|jpe?g|png)$/i,//驗證圖片格式
            maxNumberOfFiles : 1,//最大上傳文件數目
            maxFileSize : 1000000, // 文件上限1MB
            minFileSize : 100,//文件下限  100b
            messages : {//文件錯誤信息
                acceptFileTypes : '文件類型不匹配',
                maxFileSize : '文件過大',
                minFileSize : '文件過小'
            }
        })
        //圖片添加完成后觸發的事件
        .on("fileuploadadd", function(e, data) {
            //validate(data.files[0])這里也可以手動來驗證文件格式和大小
            
            //隱藏或顯示頁面元素
            $('#progress .bar').css( 
                'width', '0%'
              );
            $('#progress').hide();
            $("#chooseFile").hide();
            $("#uploadFile").show();
            $("#rechooseFile").show();
            
            //獲取圖片路徑並顯示
            var url = getUrl(data.files[0]);
            $("#image").attr("src", url);
            
            //綁定開始上傳事件
            $('#uploadFile').click(function() {
                $("#uploadFile").hide();
                jqXHR = data.submit();
                //解綁,防止重復執行
                $("#uploadFile").off("click"); 
            })
            
            //綁定點擊重選事件
            $("#rechooseFile").click(function(){
                $("#uploadImg").click();
                //解綁,防止重復執行
                $("#rechooseFile").off("click"); 
            })
        })
        //當一個單獨的文件處理隊列結束觸發(驗證文件格式和大小)
        .on("fileuploadprocessalways", function(e, data) {
            //獲取文件
            file = data.files[0];
            //獲取錯誤信息
            if (file.error) {
                console.log(file.error);
                $("#uploadFile").hide();
            }
        })
        //顯示上傳進度條
        .on("fileuploadprogressall", function(e, data) {
            $('#progress').show();
             var progress = parseInt(data.loaded / data.total * 100, 10); 
              $('#progress').css( 
               'width','15%'
              ); 
              $('#progress .bar').css( 
               'width',progress + '%'
              ); 
        })
        //上傳請求失敗時觸發的回調函數
        .on("fileuploadfail", function(e, data) {
            console.log(data.errorThrown);
        })
        //上傳請求成功時觸發的回調函數
        .on("fileuploaddone", function(e, data) {
            alert(data.result);
            
        })
        //上傳請求結束后,不管成功,錯誤或者中止都會被觸發
        .on("fileuploadalways", function(e, data) {
 
        })
 
        
        //手動驗證
        function validate(file) {
            //獲取文件名稱
            var fileName = file.name;
            //驗證圖片格式
            if (!/.(gif|jpg|jpeg|png|gif|jpg|png)$/.test(fileName)) {
                console.log("文件格式不正確");
                return true;
            }
            //驗證excell表格式
            /*  if(!/.(xls|xlsx)$/.test(fileName)){
                 alert("文件格式不正確");
                 return true;
             } */
 
            //獲取文件大小
            var fileSize = file.size;
            if (fileSize > 1024 * 1024) {
                alert("文件不得大於一兆")
                return true;
            }
            return false;
        }
 
        //獲取圖片地址
        function getUrl(file) {
            var url = null;
            if (window.createObjectURL != undefined) {
                url = window.createObjectURL(file);
            } else if (window.URL != undefined) {
                url = window.URL.createObjectURL(file);
            } else if (window.webkitURL != undefined) {
                url = window.webkitURL.createObjectURL(file);
            }
            return url;
        }
 
    });

 四、基於Base64壓縮的圖片上傳

圖片的Base64 編碼就是可以將一副圖片數據編碼成一串字符串,使用該字符串代替圖像地址。例如:

 

 

基於Base64實現圖片上傳其實就是在瀏覽器端先將圖片轉換成字符串,然后將代表圖片的字符串傳輸到服務器進行存儲。需要顯示的時候可以將字符串寫入<img src="">直接顯示。

該圖片上傳的方式比較簡單,且沒有其他的例如跨域提交、頭文件等問題。但是其編碼后的字符串大小遠遠大於實際的圖片大小。所以只適合上傳小尺寸的圖片,例如用戶頭像等。

1、頁面代碼

$("#img").change(function (e) {
        var img = e.target.files[0];
        var reader = new FileReader();
        reader.readAsDataURL(img);
        reader.onload = function (e) {
        // ajax 上傳圖片
          $.post("uploadPic", {img: e.target.result}, function (ret) {
             if (ret.img != '') {
                //顯示圖片
                $('#showimg').attr("src", ret.imgUrl);
             }
          }, 'json');
    } });

2、服務器接收到Base64字符串,就可以得到圖片並且將圖片直接存入數據庫。這里不再描述。

 五、配置圖片訪問路徑

1、Springboot中可以使用下面的代碼將虛擬路徑/image/**下的圖片映射成到D://盤下。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**
 * 圖片絕對地址與虛擬地址映射
 * 訪問地址示例:http://localhost:8080/image/1.png
 */

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //windows
        //registry.addResourceHandler("/image/**").addResourceLocations("file:d://upload/");
        //linux和mac
        registry.addResourceHandler("/image/**").addResourceLocations("file:/Users/David/upload/");
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    }

}

 2、如果使用springMVC的SSM框架,則可以在tomcat的service.xml文件中直接配置虛擬路徑,代碼如下:

<Context docBase="/Users/David/upload" path="/image" reloadable="true"/>

 

 

參考資料:

https://www.imooc.com/article/27804

 


免責聲明!

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



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