【问题标题】:how to get source file in HttpRequest for uploading file如何在HttpRequest中获取源文件以上传文件
【发布时间】:2011-04-21 01:54:30
【问题描述】:

我在使用 java 的 REST Web 服务中上传文件时遇到问题。我不知道如何获取源文件。 curl命令就是这样的

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

我的问题是,有人知道如何在 REST Web 服务 @PUT 方法中获取源文件 url“/home/student1/text1.txt”吗?或者任何其他方式获取它?

谢谢

【问题讨论】:

  • 该文件在客户端计算机上,因此您无法从服务器访问它,还是我遗漏了什么?
  • 但是为了上传文件我需要知道 URL,对吗? BufferedReader in=new BufferedReader(new FileReader("/home/student1/text1.txt"); 这样我就可以阅读它。因为我是网络服务的新手。而且我混淆了服务器端和客户端
  • 文件作为多部分表单的一部分遇到 HTTP 请求。您应该花一些时间来学习 HTTP 的工作原理(GET、POST、DELETE 请求和响应)。在当今世界,这是非常宝贵的
  • 请看我下面的评论,这个 curl 示例使用 PUT 而不是 multipart/form-data。

标签: java web-services rest file-upload httprequest


【解决方案1】:

我对 JAX-RS 不是很熟悉,但我认为以下代码可以满足您的需求:

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();
    }

}

我尚未验证尝试将.. 用于userdirectory 是否安全,因此可能需要输入卫生。此外,需要更好地处理错误和异常。

我使用 curl 对此进行了测试,它在服务器文件系统上创建了包含通过 --upload-file 传递的文件内容的文件,然后可以通过向同一资源发出 GET 来检索该文件。我确实必须将 Content-Type 标头添加到 curl 请求中才能使其正常工作:

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

我使用Restlet's 实现JAX-RS 对此进行了测试。

这个新版本处理了支持您在其他评论中提到的查询参数的额外要求。我将它重构为使用属性而不是方法参数,因为参数列表变得越来越笨拙。我从 JAX-RS 规范中了解到这样做是线程安全的。此外,我修改了代码以支持纯文本和二进制文件,尽管我没有尝试过使用不同的文件编码。由于该方法需要一个字节数组输入,我希望 JAX-RS 框架做正确的事情,并且如果在请求的 Content-Type 标头中提供了一种编码,则可以判断使用哪种编码。

【讨论】:

  • 你好,上传图片和zip文件出错,你知道怎么解决吗?
  • 您可能需要更正 Content-Type。我提供的示例仅适用于 Content-Type text/plain。此外,使用 Writer 和 Reader 对象不适用于图像或 zip 文件等二进制数据。您需要使用 OutputStream 和 InputStream 对象。
  • 嗨 laz,我想在 url 中获取值“名称”和“类型”的参数:localhost:8080/project/resources/user/… 你知道我怎样才能同时获取名称和类型的值吗?我使用了查询参数,但我只得到名称的值。谢谢
  • 嗨,你知道如何隐藏命令吗?现在当我们上传文件时,我们需要这样写: curl -v -T /home/student1/file.jpg localhost:8080/project/resources/user/file.jpg 。我想知道是否可以在不知道上传路径的情况下上传: curl -v localhost:8080/project/resources/user/file.jpg 。你知道如何隐藏源文件吗?
  • 我不确定这是否可行。 -T 告诉 curl 要发送什么数据。您可以像这样缩短命令,尽管curl -v -T /home/student1/file.jpg http://localhost:8080/project/resources/user/sub-folder/ 将文件名从目标 URL 中去掉,并且 curl 将使用通过 -T 传递的文件名。 curl 似乎不喜欢添加了查询参数,所以如果你需要那些你需要提供文件名。
【解决方案2】:

我假设 curl 使用 mltipart/form-data 作为上传的内容类型。 文件名将是第一个 MIME 部分的 Content-Disposition 标头的一部分。

【讨论】:

  • curl 的 --upload-file 选项告诉它将文件内容作为 HTTP PUT 请求的主体发送,而不是多部分/表单数据格式。
  • 感谢您的更正。在这种情况下,没有标准的机制来传输原始文件名
  • 嗨,你知道如何从 PUT 请求中获取文件的内容吗?谢谢
  • 我不确定为什么选择这个答案,因为它不正确。示例 curl 命令不使用 multipart/form-data。您可能应该遵循上述 Milimetric 的建议并熟悉 HTTP。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-17
  • 1970-01-01
  • 2013-04-11
  • 2017-02-20
  • 2016-01-14
  • 2017-11-19
  • 2016-07-30
相关资源
最近更新 更多