Uploading files with PUT

When a webdav client uploads a file its done with a PUT request, but when done from a web browser its done with a POST. Milton supports both but handing POST's it outside the scope of this module, instead we'll just talk about PUT.

Milton implements support for webdav as operations on resources. When you upload a file which doesnt exist yet thats considered an operation on the folder you're uploading to. If the file does exist then milton considers that a replace operation on that file.

So to support uploading new files implement PutableResource on your folder class, and to implement replacing existing files implement ReplaceableResource on the file class.

In our example project the SolarSystemResource class represents a folder which contains text files, where each text file is the data for a planet. So to allow new planet files to be uploaded like this:

public class SolarSystemResource extends AbstractResource implements CollectionResource, MoveableResource, PutableResource {

    private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(SolarSystemResource.class);
    private ArrayList<Resource> children;
    private final GalaxyResource parent;
    private final SolarSystem solarSystem;

    public SolarSystemResource(GalaxyResource parent, SolarSystem solarSystem) {
        this.parent = parent;
        this.solarSystem = solarSystem;

    public Resource createNew(String newName, InputStream inputStream, Long length, String contentType) throws IOException, ConflictException, NotAuthorizedException, BadRequestException {
        Planet p = solarSystem.addPlanet(newName);
        PlanetResource r = new PlanetResource(this, p);
        r.replaceContent(inputStream, length);
        return r;

Note that the class declaration implements PutableResource and the createNew method creates the new object and returns a reference to the created resource. The createNew actually delegates to the replaceContent method on PlanetResource, so we'd better create it...

Note that this will also allow you to overwrite existing files, because milton will delete and recreate the file if it does not implement ReplaceableResource, but it is recomended that you dont rely on this.

So next implement ReplaceableResource on PlanetResource like this:

public class PlanetResource extends AbstractResource implements GetableResource, ReplaceableResource, MoveableResource{

    private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(PlanetResource.class);
    private final SolarSystemResource parent;
    private final Planet planet;

    public PlanetResource(SolarSystemResource parent, Planet planet) {
        this.parent = parent;
        this.planet = planet;

    public void sendContent(OutputStream out, Range range, Map<String, String> params, String contentType) throws IOException {
        Properties props = new Properties();
        if( planet.getType() == null ) {
            props.setProperty("type", "");
        } else {
            props.setProperty("type", planet.getType());
        props.setProperty("radius", planet.getRadius() + "" );
        props.setProperty("yearLength", planet.getYearLength() + "" );
        props.store(out, null);

    public void replaceContent(InputStream in, Long length) throws BadRequestException, ConflictException, NotAuthorizedException {
        Properties props = new Properties();
        try {
        } catch (IOException ex) {
            throw new BadRequestException("Couldnt read properties", ex);

Here we're parsing the incoming data and populating the planet's properties from it.

Try it yourself and check that you can upload new files and edit existing files.

You should be able to edit the files in place in the webserver, depending on how you've connected. For example Nautilus on Linux allows you to directly open and edit text files.

Next Article:

Downloading files