Grails示例程序-将附件保存到数据库

本示例有两个工作页面,一个用来显示文档信息列表,一个用来上传文档到服务器。

  • Domain

该文档对象将保存到这里域模型中


package com.tutorial

class Document {

    String filename
    byte[] filedata
    Date uploadDate = new Date()
    static constraints = {
        filename(blank:false,nullable:false)
        filedata(blank: true, nullable:true, maxSize:1073741824)
    }
}

filedata使用byte[]类型,允许最大值在constraints{}中定义

  • 列表

使用一个列表存放上传到服务器的文档信息,下面是列表的controller和view


package com.tutorial

class DocumentController {
    def index() {
        redirect(action: "list", params: params)
    }

    def list() {
        params.max = 10
        [documentInstanceList: Document.list(params), documentInstanceTotal: Document.count()]
    }
}

访问index时重定向到list,下面是list.gsp


<!DOCTYPE html>
<html>
    <head>
        <meta name="layout" content="main">
        <title>Document List</title>
    </head>
    <body>
        <div class="nav" role="navigation">
            <ul><li><g:link class="create" action="create">Upload New Document</g:link></li></ul>
        </div>
        <div class="content scaffold-list" role="main">
        <h1>Document List</h1>
            <g:if test="${flash.message}"><div class="message" role="status">${flash.message}</div></g:if>
            <table>
                <thead>
                    <tr>
                        <g:sortableColumn property="filename" title="Filename" />
                        <g:sortableColumn property="uploadDate" title="Upload Date" />
                    </tr>
                </thead>
                <tbody>
                    <g:each in="${documentInstanceList}" status="i" var="documentInstance">
                        <tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
                            <td><g:link action="download" id="${documentInstance.id}">${documentInstance.filename}</g:link></td>
                            <td><g:formatDate date="${documentInstance.uploadDate}" /></td>
                        </tr>
                    </g:each>
                </tbody>
            </table>
            <div class="pagination">
                <g:paginate total="${documentInstanceTotal}" />
            </div>
        </div>
    </body>
</html>

在列表中的download列,下载链接指的是文档的id,显示文档的文件名。

  • 上传

Upload New Document 链接导航到文档上传页面,下面是controller和view代码

create.gsp


<%@ page import="com.tutorial.Document" %>
<!DOCTYPE html>
<html>
    <head>
        <meta name="layout" content="main">
        <title>Upload New Document</title>
    </head>
    <body>
        <div class="nav" role="navigation">
            <ul><li><g:link class="list" action="list">Document List</g:link></li></ul>
        </div>
        <div class="content scaffold-create" role="main">
            <h1>Upload New Document</h1>
                <g:if test="${flash.message}"><div class="message" role="status">${flash.message}</div></g:if>
                <g:uploadForm action="upload">
                    <fieldset class="form">
                        <input type="file" name="file" />
                    </fieldset>
                    <fieldset class="buttons">
                        <g:submitButton name="upload" class="save" value="Upload" />
                    </fieldset>
            </g:uploadForm>
        </div>
    </body>
</html>

controller


def create() {
}

def upload() {
    def file = request.getFile('file')
    if(file.empty) {
        flash.message = "File cannot be empty"
    } else {
        def documentInstance = new Document()
        documentInstance.filename = file.originalFilename
        documentInstance.filedata = file.getBytes()
        documentInstance.save()
    }
    redirect (action:'list')
}

documentInstance.filedata = file.getBytes()获取到文档的字节数,保存到document对象中。

  • 下载

下载代码也非常精简


def download(long id) {
    Document documentInstance = Document.get(id)
    if ( documentInstance == null) {
        flash.message = "Document not found."
        redirect (action:'list')
    } else {
        response.setContentType("APPLICATION/OCTET-STREAM")
        response.setHeader("Content-Disposition", "Attachment;Filename=\"${documentInstance.filename}\"")

        def outputStream = response.getOutputStream()
        outputStream << documentInstance.filedata
        outputStream.flush()
        outputStream.close()
    }
}

outputStream « documentInstance.filedata这句代码用来检索字节内容并发送给response对象。

点这里可以下载完整代码打包

  • 如果使用文件系统保存,在数据库中只保存文件路径,需要修改的地方如下

1.修改domain:将filedata修改成文档路径,String fullPath
2.配置一个文件保存到服务器的物理地址,修改config/Config.groovy


environments {
    development {
        uploadFolder = "c:/temp/upload/"
    }
    test {
        uploadFolder = "c:/temp/upload/"
    }
    production {
        uploadFolder = "c:/temp/upload/"
    }
}

3.修改文档上传的controller


def upload() {
    def file = request.getFile('file')
    if(file.empty) {
        flash.message = "File cannot be empty"
    } else {
        def documentInstance = new Document()
        documentInstance.filename = file.originalFilename
        documentInstance.fullPath = grailsApplication.config.uploadFolder + documentInstance.filename
        file.transferTo(new File(documentInstance.fullPath))
        documentInstance.save()
    }
    redirect (action:'list')
}

4.修改文档下载的controller


def download(long id) {
    Document documentInstance = Document.get(id)
    if ( documentInstance == null) {
        flash.message = "Document not found."
        redirect (action:'list')
    } else {
        response.setContentType("APPLICATION/OCTET-STREAM")
        response.setHeader("Content-Disposition", "Attachment;Filename=\"${documentInstance.filename}\"")

        def file = new File(documentInstance.fullPath)
        def fileInputStream = new FileInputStream(file)
        def outputStream = response.getOutputStream()

        byte[] buffer = new byte[4096];
        int len;
        while ((len = fileInputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, len);
        }

        outputStream.flush()
        outputStream.close()
        fileInputStream.close()
    }
}

你可能感兴趣的:(Grails示例程序-将附件保存到数据库)