Java實現Nginx圖片上傳

簡介

文件上傳功能,是信息系統開發中的常用功能,在傳統的開發流程中,前端通過表單上傳文件,後端進行文件處理。不利之處在於

  1. 後端需要寫重複代碼,每開發一個包含上傳功能的系統,就需要寫一遍上傳邏輯。
  2. 當文件未保存在共享服務器時,其它開發人員無法獲取上傳的文件的正確地址。
  3. 當文件保存在共享文件系統時,需要對共享文件系統進行讀寫獲取對應文件。

       基於以上不利之處,我們結合包含了upload_module和upload-progress_module的nginx,以及nginx本身作爲http服務器的特性,設計了本文件上傳服務器,希望能減少大家的開發量。

1.文件上傳服務器原理

2.部署Nginx上傳服務器

部署Nginx上傳服務器在上一篇文章已經說明,這裏就不再贅述,詳見docker 安裝 Nginx 作爲上傳服務器

啓動Nginx。

3.上傳控件的使用

    ①使用iframeUplaod上傳文件插件,該代碼基本原理就是動態創建一個iframe,在iframe中再增加一個form,最後數據放到這個form中提交給服務器,前端代碼如下:

<body>
<div id="uploadFile" class="upload">

</div>
<a href="javascript:void(0);" id="submit">提交</a>
<div class="pic-upload fl">
    <div id="imgPreview">
        <img class="picIcon" id="picIcon" src="${basePath}/resources/theme/images/user_default.jpg">
    </div>
    <input type="hidden" id="iconUrl" value="${basePath}/resources/theme/images/user_default.jpg">
</div>
<script src="${basePath}/resources/others/jquery/jquery-1.8.3.min.js"></script>
<script src="${basePath}/resources/upload/iframeUpload.js"></script>
<script language="javaScript">
    $(function () {
        var localPath = 'http://'+document.domain + ":" +
                window.location.port + basePath+"/result";
        var submitForm = IframeUpload.create({
            id: "1",
            url: basePath+"/fastdfs/systemIcon",
            //progressUrl:"http://192.168.2.125:10000/progress",
            interval:300,
            containerId: 'uploadFile',
            resultPath:localPath,
            success: function (res) {
            	if (res.result == 'success') {
                    $("#iconUrl").val(res.msg);
                    $(".picIcon").attr('src', res.msg);
                } else {
                	alert("上傳失敗!!!");
                }
            },
        });

        $('a#submit').click(function(){
            submitForm.submit();
        });
    });
 </script>
</body>

 

②如何在Java應用中集成上傳文件組件

    ●在項目的pom.xml文件中添加相關依賴 

<dependency>
	<groupId>com.jcraft</groupId>
	<artifactId>jsch</artifactId>
	<version>0.1.54</version>
</dependency>
<dependency>
	<groupId>com.jcabi</groupId>
	<artifactId>jcabi-ssh</artifactId>
	<version>1.5.2</version>
</dependency> 
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.8</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.3.2</version>
</dependency>

      這裏省略了spring相關依賴,若需要其他依賴,讀者可自行查找添加。

    ●將config.properties中的內容複製到項目所在的properties文件中,並配置以下內容

remote.host=192.168.2.125           #文件上傳服務器ip
remote.port=22                      #文件上傳服務器的SSH端口
remote.user=root                    #文件上傳服務器的SSH用戶名
remote.password=123456              #文件上傳服務器的密碼
remote.dir=/root/nginx/files/       #nginx配置的上傳文件目錄
nginx.port=10000                    #nginx中配置監聽的端口
nginx.fileuri=/files                #nginx配置轉發文件uri
remote.extern.host=192.168.2.125    #訪問路徑的host

    ●在spring-mvc.xml文件中引入conf.properties文件

<bean id="appProperty"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
         <array>
             <value>classpath:conf.properties</value>
          </array>
    </property>
</bean>

    ●在spring-mvc.xml文件中配置文件上傳解析器

<!-- 文件上傳解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="UTF-8"></property>
    <property name="maxUploadSize" value="524288000"></property>
</bean>

● 編寫上傳文件工具類,獲取上傳後的圖片地址以及重命名文件

package com.eshore.upload.util;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.jcabi.ssh.SSHByPassword;
import com.jcabi.ssh.Shell;

@Component
public class FileUploadUtil {
    @Value("${remote.host}")
    private String remoteHost;

    @Value("${remote.port}")
    private String remotePort;

    @Value("${remote.user}")
    private String remoteUser;

    @Value("${remote.password}")
    private String remotePassword;

    @Value("${remote.dir}")
    private String remoteDir;

    @Value("${nginx.port}")
    private String nginxPort;

    @Value("${nginx.fileuri}")
    private String nginxFileUri;

    public String getUrlFromRequest(HttpServletRequest request,String filename) throws NullPointerException{
        StringBuilder builder = new StringBuilder("http://");
        builder.append(remoteHost);
        builder.append(":");
        builder.append(nginxPort);
        builder.append(nginxFileUri);
        builder.append("/");
        builder.append(filename);
        return builder.toString();
    }

    public String renameFile(HttpServletRequest request) throws IOException,NullPointerException{
		Shell shell = new SSHByPassword(remoteHost, Integer.valueOf(remotePort), remoteUser, remotePassword);

		Shell.Plain plain = new Shell.Plain(shell);

		String orgFile = request.getParameter("file_name");

		if (orgFile == null) {
			throw new NullPointerException("文件名不存在");
		}
		orgFile.replaceAll(" ", "");
		String hostFile = request.getParameter("file_path");
		if (hostFile == null) {
			throw new NullPointerException("文件路徑不存在");
		}

		String timestamp = new SimpleDateFormat("YYYY-MM-dd-HH-mm-ss").format(new Date()).toString();
		String filename = new StringBuilder(timestamp).append("-").append(orgFile).toString().replaceAll(" ", "").replaceAll("/", "");

		String hostFilePath = remoteDir.concat(hostFile.substring(hostFile.lastIndexOf("/") + 1));
		String orgFilePath = remoteDir.concat(filename);

		String renameCmd = new StringBuilder("mv ").append("\'").append(hostFilePath).append("\'").append(" ")
				.append("\'").append(orgFilePath).append("\'").toString();

		String result = plain.exec(renameCmd);

		if (!result.isEmpty()) {
			throw new NullPointerException("命令運行失敗,請檢查文件名是否有特殊符號,如()");
		}

		return filename;
    }
}

    ●Controller層處理,返回結果,圖片url入庫

package com.eshore.upload.controller;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.view.RedirectView;

import com.eshore.upload.util.FileUploadUtil;

@Controller
public class UploadController {
	
	@Autowired
    private FileUploadUtil fileUploadUtil;
	
	@RequestMapping("/hello")
	public String hello() {
		return "hello";
	}
	
	@RequestMapping("/systemIcon")
    public RedirectView uploadSystemIcon(HttpServletRequest request,
                                         HttpServletResponse response, RedirectAttributes ra) {
        String url = null; //這個URL是最終跳轉返回的URL,本實例中,爲/upload/result
        String newUrl = request.getParameter("org");
        try {

            //重命名文件名稱
            String filename = fileUploadUtil.renameFile(request);
            //獲取返回的URL
            url = fileUploadUtil.getUrlFromRequest(request, filename);
            /**
             * 如果需要保存圖片信息,這裏可以將url存入到數據庫
             */
        } catch (NullPointerException | IOException e) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            ra.addAttribute("result", "fail");
            ra.addAttribute("msg", "exception happened");
            return new RedirectView(newUrl);
        }

        ra.addAttribute("result", "success");
        ra.addAttribute("msg", url);
        
        return new RedirectView(newUrl);
    }

    @RequestMapping("/result")
    public ModelAndView result(HttpServletRequest request) throws IOException {
        ModelAndView view = new ModelAndView("upload/result");
        return view;
    }
    
    @RequestMapping("/file")
    public ModelAndView file(HttpServletRequest request) throws IOException {
        ModelAndView view = new ModelAndView("upload/upload");
        return view;
    }

}

4.項目源碼

    項目源碼已同步到GitHub:https://github.com/yinZh0522/nginx-upload

      

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章