2015年10月4日 星期日

上傳 (Struts2.3.x 十一)

上傳首先要有兩個jar,看這裡
先寫個type="file",看看Action抓到的情形
upload.jsp
<form action="upload!upload.action" method="post" enctype="multipart/form-data">
    <input type="file" name="uploadFile" /><br /> 
    <input type="submit" />
</form>


struts.xml,因為action沒有result,待會會出錯,但目前只要看控制台的訊息就好
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.custom.i18n.resources" value="Message" />
<constant name="struts.devMode" value="true" />

<package name="basicstruts2" extends="struts-default" namespace="/struts2">
    <action name="upload" class="action.UploadAction"></action>
</package>


UploadAction.java,只要繼承ActinSupport
public class UploadAction extends ActionSupport {
    private File uploadFile;
    //setter即可

    public String upload() {
        System.out.println("uploadFile=" + uploadFile);
        return null;
    }
}


抓到的檔案副檔名為tmp,而且控制台部分訊息出現「'uploadFileContentType' on 'class action.UploadAction」和「'uploadFileFileName' on 'class action.UploadAction」的訊息,表示要增加這兩個屬性,所以Action最後的結果要改成如下的方式:

public class UploadAction extends ActionSupport {
    private File uploadFile;
    private String uploadFileContentType;
    private String uploadFileFileName;
    //三個屬性都給setter即可

    public String upload() {
        System.out.println("uploadFile=" + uploadFile);
        System.out.println("uploadFileContentType=" + uploadFileContentType);
        System.out.println("uploadFileFileName=" + uploadFileFileName);
        return null;
    }
}

這裡也有說明

知道這三個屬性的關係後,重新再寫一次

upload.jsp
<%@ page isELIgnored="false"%>

${uploadMsg}
<form action="upload!upload.action" method="post" enctype="multipart/form-data">
    <input type="file" name="uploadFile" /><br /> 
    <input type="submit" />
</form>

struts.xml,constant可以在src下建立一個struts.properties,也是一樣,目前這隻saveDir還沒有作用
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.custom.i18n.resources" value="Message" />
<constant name="struts.devMode" value="true" />
<constant name="struts.multipart.saveDir" value="D:\testStruts2" />
<constant name="struts.multipart.maxSize" value="2097152" />

<package name="basicstruts2" extends="struts-default" namespace="/struts2">
    <action name="upload" class="action.UploadAction">
        <result name="success">/struts2/upload.jsp</result>
    </action>
</package>
struts2-core-2.x.x.jar\org.apache.strtus2\default.properties可以找到constant的所有資訊
2097152單位是bit,除兩次1024就是2MB

UploadAction.java
private File uploadFile;
private String uploadFileContentType;
private String uploadFileFileName;
//三個屬性都給setter即可

public String upload() {
    HttpServletRequest request = ServletActionContext.getRequest();

    //可以到「tomcat目錄\conf\web.xml」可看到很多xxx/xxx
    List<String> list = Arrays.asList(new String[] { "image/jpeg",
            "image/bmp", "image/tiff" });

    if (list.contains(this.uploadFileContentType)) {
        ServletContext context = ServletActionContext.getServletContext();
        StringBuffer path = new StringBuffer();
        // 取個資料夾名稱放上傳的檔案
        path.append(context.getRealPath("/uploadPlace"));
        // 用唯一值命名主檔名
        path.append(File.separator + UUID.randomUUID() + ".");
        // 取原本的副檔名
        path.append(this.uploadFileFileName
                .substring(this.uploadFileFileName.lastIndexOf(".") + 1));

        FileControl.saveFile(this.uploadFile, path.toString());
        request.setAttribute("uploadMsg", "上傳成功!");
    } else {
        request.setAttribute("uploadMsg", "上傳非圖片格式!");
    }
    return SUCCESS;
}

FileControl.java,裡面只有兩個靜態方法
public static boolean saveFile(File file, String path) {
    File outFile = new File(path);
    if (!outFile.getParentFile().exists()) {
        outFile.getParentFile().mkdirs();
    }
    InputStream input = null;
    OutputStream output = null;
    try {
        input = new FileInputStream(file);
        output = new FileOutputStream(outFile);
        byte[] data = new byte[1024];
        int temp = 0;
        while ((temp = input.read(data)) != -1) {
            output.write(data, 0, temp);
        }
        input.close();
        output.close();
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

public static boolean deleteFile(String path) {
    File file = new File(path);
    if (file.exists()) {
        file.delete();
        return true;
    }
    return false;
}
這個class就隨個人發揮了

以上雖然完成了功能,但是是屬於自己寫的苦功,所以stuts.xml的saveDir(儲存路徑)沒有效果,當然路徑也可以用Action裡的ServletActionContext.getServletContext().getRealPath("")取得檔案內容,然後進一步取得路徑

※用struts2的攔截器來達成上傳的功能

upload.jsp
${fieldErrors},<br />
${fieldErrors['uploadFile']},<br />
${fieldErrors['uploadFile'][0]}<br />
<form action="upload!upload.action" method="post" enctype="multipart/form-data">
    <input type="file" name="uploadFile" /><br /> 
    <input type="submit" />
</form>

struts.xml,saveDir是暫存目錄,不加會在control有警告「Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir」,但不影響上傳功能,而這個資料夾,上傳完成後,我也沒看到有什麼檔案在裡面
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.custom.i18n.resources" value="Message" />
<constant name="struts.devMode" value="false" />
<constant name="struts.multipart.saveDir" value="D:/testStruts2" />

<package name="basicstruts2" extends="struts-default"
        namespace="/struts2">
    <action name="upload" class="action.UploadAction">
        <interceptor-ref name="fileUpload">
            <param name="allowedTypes">
                image/jpeg,image/bmp,image/tiff,image/png,image/gif
            </param>
            <param name="maximumSize">1048576</param>
        </interceptor-ref>
        <interceptor-ref name="basicStack"/>
        <result name="success">/struts2/upload.jsp</result>
    </action>
</package>

UploadAction
private File uploadFile;
private String uploadFileContentType;
private String uploadFileFileName;
//都給setter即可

public String upload() {
    ServletContext context = ServletActionContext.getServletContext();
    StringBuffer path = new StringBuffer();
    path.append(context.getRealPath("/uploadPlace"));
    path.append(File.separator + this.uploadFileFileName);
    System.out.println("path=" + path);
    FileControl.saveFile(this.uploadFile, path.toString());
    return SUCCESS;
}

Message.properties,顯示錯誤訊息用,不加也有預設的錯誤訊息
struts.messages.error.uploading=aaa
struts.messages.error.file.too.large=bbb
struts.messages.error.content.type.not.allowed=ccc
struts.messages.error.file.extension.not.allowed=ddd

※多檔案上傳

以上個檔案為例,其實只要變成陣列的型式就可以了
upload.jsp
<form action="upload!upload.action" method="post" enctype="multipart/form-data">
    <input type="file" name="uploadFile" />${fieldErrors['uploadFile'][0]}<br /> 
    <input type="file" name="uploadFile" />${fieldErrors['uploadFile'][1]}<br /> 
    <input type="file" name="uploadFile" />${fieldErrors['uploadFile'][2]}<br /> 
    <input type="submit" />
</form>

UploadAction.java
private File[] uploadFile;
private String[] uploadFileContentType;
private String[] uploadFileFileName;
//都給setter即可

public String upload() {
    ServletContext context = ServletActionContext.getServletContext();
    for (int i = 0; i < uploadFile.length; i++) {
        StringBuffer path = new StringBuffer();
        path.append(context.getRealPath("/uploadPlace"));
        path.append(File.separator + this.uploadFileFileName[i]);
        System.out.println("path=" + path);
        FileControl.saveFile(this.uploadFile[i], path.toString());
    }
    return SUCCESS;
}


沒有留言:

張貼留言