how to get source file in HttpRequest for uploadin

2019-04-15 02:12发布

I have a problem with upload file in REST web service using java. I don't know how to get the source file. The curl command is like that

curl --upload-file /home/student1/text1.txt http://localhost:20260/project/resources/user1/sub-folder/text1.txt

My question is anyone know how to get the source file url "/home/student1/text1.txt" in REST web service @PUT method?Or any other way to get it?

thanks

2条回答
何必那么认真
2楼-- · 2019-04-15 02:21

I'm not terribly familiar with JAX-RS but I think the following code does what you are looking for:

package org.restlet.example;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

@Path("project/resources/{user}/{directory}/{filename}")
public class JaxRsResource {
    private static final int BLOCK_SIZE = 8192;
    private static final Map<String, MediaType> MEDIA_TYPE_MAP = new HashMap<String, MediaType>();

    @Context
    private UriInfo uriInfo;

    @Context
    private HttpHeaders httpHeaders;

    @PathParam("user")
    private String user;

    @PathParam("directory")
    private String directory;

    @PathParam("filename")
    private String filename;

    @QueryParam("name")
    private String name;

    @QueryParam("type")
    private String type;

    static {
        MEDIA_TYPE_MAP.put("txt", MediaType.TEXT_PLAIN_TYPE);
        MEDIA_TYPE_MAP.put("gif", MediaType.valueOf("image/gif"));
        MEDIA_TYPE_MAP.put("jpg", MediaType.valueOf("image/jpeg"));
        MEDIA_TYPE_MAP.put("png", MediaType.valueOf("image/png"));
        MEDIA_TYPE_MAP.put("zip", MediaType.valueOf("application/zip"));
    }

    public JaxRsResource() {
    }

    @PUT
    @Consumes({"text/plain", "image/jpeg", "image/png", "image/gif", "application/zip"})
    public Response upload(final byte[] contents) throws IOException, URISyntaxException {
        FileOutputStream output = null;
        try {
            final File directories = new File(user, directory);
            directories.mkdirs();
            final File file = new File(directories, filename);
            output = new FileOutputStream(file);
            output.write(contents);
        } finally {
            if (output != null) {
                output.flush();
                output.close();
            }
        }
        return Response.created(uriInfo.getAbsolutePath()).build();
    }

    @GET
    @Produces({"text/plain", "image/jpeg", "image/png", "image/gif", "application/zip"})
    public Response output() throws IOException {
        final String extension = filename.substring(filename.lastIndexOf('.') + 1);
        final ByteArrayOutputStream output = new ByteArrayOutputStream();
        InputStream input = null;
        try {
            input = new FileInputStream(new File(new File(user, directory), filename));
            final byte[] buffer = new byte[BLOCK_SIZE];
            int read = 0;
            while ((read = input.read(buffer)) > -1) {
                output.write(buffer, 0, read);
            }
        } finally {
            if (input != null) {
                input.close();
            }
        }
        final byte[] byteArray = output.toByteArray();
        output.flush();
        output.close();
        return Response.ok(byteArray, MEDIA_TYPE_MAP.get(extension)).build();
    }

}

I haven't verified that it is safe against trying to put .. for either user or directory so it might require input sanitation. Also, the errors and exceptions needs to be handled better.

I tested this out with curl and it creates the file on the server file system containing the contents of the file passed via --upload-file which can then be retrieved by issuing a GET to the same resource. I did have to add the Content-Type header to the curl request to get it working though:

curl -v -T test.txt -H "Content-Type: text/plain" http://localhost:8182/project/resources/user1/sub-folder/test.txt

I tested this out using Restlet's implementation of JAX-RS.

This new version handles your additional requirement of supporting the query parameters you mentioned in the other comment. I refactored it to use properties instead of method arguments, since the argument lists were growing unwieldy. I learned that it is thread safe to do so from the JAX-RS spec. Also, I modified the code to support plain text and binary files, though I haven't tried it with different file encodings. Since the method is expecting a byte array input I'm hoping that the JAX-RS framework does the right thing and can tell which encoding to use if one is provided in the request's Content-Type header.

查看更多
Explosion°爆炸
3楼-- · 2019-04-15 02:39

I'm assuming that curl uses mltipart/form-data as content type for the upload. The filename would be part of the Content-Disposition header of the first MIME part.

查看更多
登录 后发表回答