首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Uploadify + Spring MVC 實現多文件上傳與圖片預覽完整實戰

     編輯:Java 相關知識

技術棧與依賴

  • 前端:jQuery + Uploadify v3.1 (Flash/HTML5 雙模)
  • 後端:Spring MVC + Commons FileUpload + Commons IO
  • 瀏覽器兼容:IE10+、Chrome、Firefox、Edge

前端頁面整合 (index.html)

<!DOCTYPE html>
<html>
<head>
    <title>多文件上傳預覽演示</title>
    <link rel="stylesheet" href="/js/uploadify-v3.1/uploadify.css" />
    <script src="/js/jquery-3.6.0.min.js"></script>
    <script src="/js/uploadify-v3.1/jquery.uploadify-3.1.min.js"></script>
    <style>
        #uploader { position: relative; margin: 20px; }
        #uploader_queue { position: absolute; left: 130px; top: 0; width: 600px; }
        #uploader_view img { max-height: 80px; margin: 5px; border: 1px solid #ddd; }
    </style>
</head>
<body>
    <div id="uploader">
        <input type="file" name="file_upload" id="file_upload" />
        <a href="javascript:$('#file_upload').uploadify('upload','*')">開始上傳</a>
        <a href="javascript:$('#file_upload').uploadify('cancel','*')">取消全部</a>
        <div id="uploader_queue"></div>
        <div id="uploader_msg"></div>
        <div id="uploader_view"></div>
    </div>

    <script>
    $(function() {
        $('#file_upload').uploadify({
            'auto'            : false,          // 手動觸發上傳
            'method'          : 'post',
            'formData'        : { 'folder': 'file' },
            'swf'             : '/js/uploadify-v3.1/uploadify.swf',
            'uploader'        : '/uploadAttach.do',
            'buttonText'      : '選擇文件',
            'fileTypeDesc'    : '支持圖片/文檔/視頻/壓縮包',
            'fileTypeExts'    : '*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.pdf;*.doc;*.docx;*.xls;*.xlsx;*.zip;*.rar;*.mp4;*.avi;*.mov',
            'fileSizeLimit'   : '50MB',
            'uploadLimit'     : 20,
            'queueSizeLimit'  : 20,
            'queueID'         : 'uploader_queue',
            'progressData'    : 'speed',
            'removeCompleted' : false,
            'removeTimeout'   : 3,
            'onUploadSuccess' : function(file, data, response) {
                // 後端返回文件訪問路徑,前端追加預覽
                var url = '/upload/' + encodeURI(data);
                var isImg = /\.(jpg|jpeg|png|gif|bmp)$/i.test(file.name);
                var html = isImg 
                    ? '<img src="' + url + '" alt="' + file.name + '" title="' + file.name + '" />'
                    : '<div class="file-tag">📄 ' + file.name + '</div>';
                $('#uploader_view').append(html);
            },
            'onQueueComplete' : function(queueData) {
                $('#uploader_msg').html('成功上傳 ' + queueData.uploadsSuccessful + ' 個文件');
            },
            'onUploadError' : function(file, errorCode, errorMsg, errorString) {
                console.error('上傳失敗:', file.name, errorCode, errorMsg);
            }
        });
    });
    </script>
</body>
</html>

後端 Controller (Spring MVC)

@Controller
@RequestMapping("/upload")
public class UploadController {

    private static final Logger log = LoggerFactory.getLogger(UploadController.class);
    private static final String[] ALLOWED_EXTS = {".jpg",".jpeg",".png",".gif",".bmp",".pdf",".doc",".docx",".xls",".xlsx",".zip",".rar",".mp4",".avi",".mov"};

    @PostMapping("/uploadAttach")
    @ResponseBody
    public void uploadAttach(HttpServletRequest request, HttpServletResponse response) throws Exception {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();

        String basePath = request.getSession().getServletContext().getRealPath("/") + "upload/";
        File baseDir = new File(basePath);
        if (!baseDir.exists()) baseDir.mkdirs();

        StringBuilder resultPaths = new StringBuilder();
        long timestamp = System.currentTimeMillis();

        for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
            MultipartFile file = entry.getValue();
            if (file.isEmpty()) continue;

            // 1. 文件類型校驗
            String originalName = file.getOriginalFilename();
            String ext = originalName.substring(originalName.lastIndexOf(".")).toLowerCase();
            if (!Arrays.asList(ALLOWED_EXTS).contains(ext)) {
                log.warn("非法文件類型: {}", originalName);
                continue; // 或拋異常
            }

            // 2. 生成唯一文件名:時間戳_UUID_原始名
            String saveName = timestamp + "_" + UUID.randomUUID().toString().replace("-", "") + ext;
            File dest = new File(baseDir + saveName);

            // 3. 保存文件
            try (FileOutputStream fos = new FileOutputStream(dest)) {
                fos.write(file.getBytes());
                fos.flush();
            }

            resultPaths.append(saveName).append(",");
        }

        // 4. 返回文件名列表,前端拼接預覽 URL
        String resp = resultPaths.length() > 0 ? resultPaths.substring(0, resultPaths.length() - 1) : "";
        response.setContentType("text/plain;charset=UTF-8");
        response.getWriter().write(resp);
    }
}

關鍵配置說明

配置項作用建議值
auto: false手動觸發上傳,支持用戶確認後統一上傳false
fileSizeLimit單文件大小限制50MB
uploadLimit單次隊列最大文件數20
queueSizeLimit隊列最大文件數20
removeCompleted上傳成功後是否自動移除隊列項false (保留預覽)
progressData: 'speed'顯示上傳速度而非百分比'speed'

生產環境避坑指南

  1. Flash 依賴:Uploadify v3.1 仍依賴 Flash,現代瀏覽器已棄用。強烈建議遷移至 WebUploader / Plupload / Dropzone.js (純 HTML5)。
  2. 大文件分片:50MB+ 文件建議前端分片上傳,後端合併,避免超時/內存溢出。
  3. 文件類型雙重校驗:前端 accept 只能攔截善意用戶,後端必須校驗 Content-Type + Magic Number (文件頭字節)。
  4. 存儲隔離:上傳目錄應與 Web 應用根目錄分離,或配置 Nginx location /upload { internal; } 防止腳本執行。
  5. 並發安全:文件名用 UUID + timestamp 避免衝突,高併發下可加分佈式鎖或雪花算法。

總結

本文提供了 Uploadify + Spring MVC 多文件上傳預覽的完整落地代碼。但受限於 Flash 技術棧,新項目請直接選用 WebUploader 或 Dropzone.js,架構邏輯完全一致,僅前端組件替換即可。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved