Skip to content

Instantly share code, notes, and snippets.

@Zenithar
Last active December 18, 2015 23:09
Show Gist options
  • Save Zenithar/5859461 to your computer and use it in GitHub Desktop.
Save Zenithar/5859461 to your computer and use it in GitHub Desktop.
RestExpress MultiPart File Upload support
package org.zenithar.restexpress.config;
import com.strategicgains.restexpress.Format;
import com.strategicgains.restexpress.RestExpress;
import com.strategicgains.restexpress.util.Environment;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.FileCleaningTracker;
import java.io.File;
import java.util.Properties;
/**
* @author Thibault NORMAND
* @date 25/06/13
*/
public class Configuration
extends Environment {
private FileUpload fileUpload = new FileUpload();
private DeleteFilesOnEndUploadCleaningTracker fileCleaningTracker = new DeleteFilesOnEndUploadCleaningTracker();
@Override
protected void fillValues(Properties p) {
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
diskFileItemFactory.setRepository(new File("./tmp"));
diskFileItemFactory.setFileCleaningTracker(fileCleaningTracker);
this.fileUpload.setFileItemFactory(diskFileItemFactory);
}
public FileUpload getFileUpload() {
return fileUpload;
}
}
package org.zenithar.restexpress.utils;
import org.apache.commons.io.FileCleaningTracker;
import org.apache.commons.io.FileDeleteStrategy;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class DeleteFilesOnEndUploadCleaningTracker extends FileCleaningTracker {
private List<String> filesToDelete = new ArrayList();
public void deleteTemporaryFiles() {
for (String file : filesToDelete) {
new File(file).delete();
}
filesToDelete.clear();
}
@Override
public synchronized void exitWhenFinished() {
deleteTemporaryFiles();
}
@Override
public int getTrackCount() {
return filesToDelete.size();
}
@Override
public void track(File file, Object marker) {
filesToDelete.add(file.getAbsolutePath());
}
@Override
public void track(File file, Object marker, FileDeleteStrategy deleteStrategy) {
filesToDelete.add(file.getAbsolutePath());
}
@Override
public void track(String path, Object marker) {
filesToDelete.add(path);
}
@Override
public void track(String path, Object marker, FileDeleteStrategy deleteStrategy) {
filesToDelete.add(path);
}
}
package org.zenithar.restexpress.controller;
import org.zenithar.restexpress.utils.RestUploadContext;
import com.strategicgains.restexpress.Request;
import com.strategicgains.restexpress.Response;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
/**
* @author Thibault NORMAND
* @date 25/06/13
*/
public class DeliveryController {
private FileUpload fileUpload;
private DeleteFilesOnEndUploadCleaningTracker tracker;
public DeliveryController(FileUpload fileUpload, DeleteFilesOnEndUploadCleaningTracker tracker) {
super();
this.fileUpload = fileUpload;
this.tracker = tracker;
}
public void create(Request request, Response response) {
RestUploadContext context = RestUploadContext.fromRequest(request);
try {
List<FileItem> items = fileUpload.parseRequest(context);
Map<String , List<FileItem>> parts = MultiPartDecoder.getParts(items);
for(FileItem file : parts.get("files")) {
// File operation
}
catch (FileUploadException e) {
// Handle errors
} finally {
tracker.deleteTemporaryFiles();
}
}
}
package org.zenithar.restexpress.utils;
import org.apache.commons.fileupload.FileItem;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author t_no
* @date 25/06/13
*/
public final class MultiPartDecoder {
private MultiPartDecoder() {
throw new AssertionError();
}
public static Map<String, List<FileItem>> getParts(List<FileItem> request) {
Map<String, List<FileItem>> parts = new LinkedHashMap<String, List<FileItem>>();
for(FileItem it : request) {
final String partName = it.getFieldName();
if(parts.containsKey(partName)) {
parts.get(partName).add(it);
} else {
List<FileItem> items = new LinkedList<FileItem>();
items.add(it);
parts.put(partName, items);
}
}
return parts;
}
}
package org.zenithar.restexpress.utils;
import com.strategicgains.restexpress.Request;
import org.apache.commons.fileupload.UploadContext;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Thibault NORMAND
* @date 25/06/13
*/
public class RestUploadContext implements UploadContext {
private final long contentLength;
private final String characterEncoding;
private final String contentType;
private final InputStream inputStream;
private RestUploadContext(long contentLength, String characterEncoding, String contentType, InputStream inputStream) {
this.contentLength = contentLength;
this.characterEncoding = characterEncoding;
this.contentType = contentType;
this.inputStream = inputStream;
}
public static RestUploadContext fromRequest(Request request) {
return new Builder()
.withChannelBuffer(request.getBody())
.withContentType(request.getHeader("Content-Type"))
.withContentLength(Long.valueOf(request.getHeader("Content-length")))
.build();
}
public static class Builder {
private Long contentLength = 0L;
private String characterEncoding = "UTF-8";
private String contentType = "multipart/form-data";
private InputStream inputStream;
public Builder() {
}
public Builder withContentLength(long length) {
this.contentLength = length;
return this;
}
public Builder withCharacterEncoding(String encoding) {
this.characterEncoding = encoding;
return this;
}
public Builder withContentType(String contentType) {
this.contentType = contentType;
return this;
}
public Builder withChannelBuffer(ChannelBuffer channel) {
this.inputStream = new ChannelBufferInputStream(channel);
return this;
}
public RestUploadContext build() {
return new RestUploadContext(contentLength, characterEncoding, contentType, inputStream);
}
}
@Override
public long contentLength() {
return this.contentLength;
}
@Override
public String getCharacterEncoding() {
return this.characterEncoding;
}
@Override
public String getContentType() {
return this.contentType;
}
@Override
public int getContentLength() {
return Long.valueOf(this.contentLength).intValue();
}
@Override
public InputStream getInputStream() throws IOException {
return inputStream;
}
}
@phuoctran-lifestyle
Copy link

Can you write a sample for upload images?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment