Grails - 图片上传、下载、等比压缩 博客分类: Grails&Groovy文件处理
程序员文章站
2024-03-19 22:02:04
...
Grails 图片上传
<g:form controller="attachments" action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> <input type="submit" value="上传"/> </g:form>
def upload() { def file = request.getFile("file") if (file.empty) { flash.message = message(code: '请选择要上传的文件') redirect(controller: "attachments", action: "create") } def fileType = file.getOriginalFilename().split('\\.')[-1] if (!(fileType in ['jpg', 'png', 'jpeg','pdf', 'doc', 'docx'])) { flash.message = message(code: '文件格式不支持') redirect(controller: "attachments", action: "create") } def webrootDir = servletContext.getRealPath("/") File fileFolder = new File(webrootDir, "images/tempFile.${fileType}") file.transferTo(fileFolder) // 压缩图片 def fileSize = request.getContentLength() if (fileType in ['jpg', 'png', 'jpeg'] && fileSize > 1024 * 1024) { def compressImg = fileServerService.compress(fileFolder.getAbsolutePath(), 1920, 1080) fileFolder = new File(compressImg) } }
为防止过大图片消耗内存,且方便存储,决定对过大文件(>1M)进行压缩。 等比压缩,图片大小可以自己指定。若图片大小不想改变,则可以将宽高指定成屏幕大小,如:w=1920,h=1080
def compress(String fileName, Integer w, Integer h) { File file = new File(fileName) Image img = ImageIO.read(file) Integer width = img.getWidth(null) Integer height = img.getHeight(null) if (width / height > w / h) { h = (Integer) (height * w / width) } else { w = (Integer) (width * h / height) } BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB) // Image.SCALE_AREA_AVERAGING、Image.SCALE_SMOOTH 这两种方式压缩效果较好 image.getGraphics().drawImage(img.getScaledInstance(w, h, Image.SCALE_SMOOTH),0, 0, null) File destFile = new File(fileName) FileOutputStream out = new FileOutputStream(destFile) JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out) encoder.encode(image) return fileName }
目前为止,文件已经存储到项目的/images文件夹下,若想将文件统一管理,可以生产一个文件管理服务,通过接口调用,需要将图片转成Base64码传输。
def upload() { // 接上面的upload // 将临时文件存储转成 Base64 FileInputStream inputStream = new FileInputStream(fileFolder) ByteArrayOutputStream output = new ByteArrayOutputStream() byte[] fileBytes = new byte[inputStream.available()] Integer length = 0 while ((length = inputStream.read(fileBytes)) != -1) { output.write(fileBytes, 0, length) } def encoded = fileBytes.encodeBase64().toString() // 调用接口,返回文件名(包括路径+名称) def fileName = fileServerService.uploadServer(encoded, fileType) }
文件服务器接收到Base64码,进行解码形成图片后存储。
def uploadServer() { def encoded = params["encoded"] def fileType = params["fileType"] def externalId = UUID.randomUUID().toString() def fileName = "images/${externalId}.${fileType}" def webrootDir = servletContext.getRealPath("/") BASE64Decoder decoder = new BASE64Decoder() byte[] image = decoder.decodeBuffer(encoded) File fileImage = new File(webrootDir, fileName) fileImage.append(image) render externalId as JSON } def removeServer() { def externalId = params["externalId"] def fileType = params["fileType"] def webrootDir = servletContext.getRealPath("/") def fileName = "images/${externalId}.${fileType}" File file = new File(webrootDir, fileName) if (file.isFile() && file.exists()) { file.delete() render status: 200 } }