【问题标题】:File upload with Jersey, File not being decoded使用 Jersey 上传文件,文件未解码
【发布时间】:2022-01-30 18:01:44
【问题描述】:

我一直在尝试将文件上传到服务器,从 Javascript 到 Jakarta REST 服务。文件未解码,我找不到问题所在。

我在javascript中使用的上传代码是基本的FormData上传(vanillajs):

  var url=.....  
  var xhttp = new XMLHttpRequest();
  var formData = new FormData();
  xhttp.onreadystatechange = () => {
    if (this.readyState == 4)
    {
        if (this.status == 200)
        {
            if (successCallback != null) successCallback(this.responseText);
        }
        else
        {
            if (errorCallback != null) errorCallback(this.status, this.statusText);
        }
    }
  };
  xhttp.open("POST", url, true);
  formData.append("file", file);
  xhttp.send(formData);

我获取文件的方式是使用文件输入,当用户加载图像时,我会加载它的图片并使用它(React):

const [imgSrc, setImgSrc] = React.useState('');

const loadImage=(e)=>{

var file=e.target.files[0];

var reader = new FileReader();
reader.onload = (e2)=>{
    setImgSrc(e2.target.result);
}
reader.readAsDataURL(file);
  }

  <input type="file" accept="image/*" onChange={(e)=>loadImage(e)} />

这似乎工作正常。当我查看请求标头时,我看到:

Content-Type: multipart/form-data; boundary=....

有效载荷以:

开头
file: data:image/jpeg;base64,/9j/...

那么我用来接收这个的 REST 服务是:

@POST
@Path("/submit")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadImage(
        @FormDataParam("file") File fileBody,
        @FormDataParam("file") FormDataContentDisposition metadata)
{
    // set up S3 bucket, all that works fine
            s3.putObject("mybucket", "pick_a_name", new FileInputStream(fileBody), null);
}

这行得通,但是文件内容是有效负载的文字内容:

data:image/jpeg;base64,/9j/...

因此它不会被识别为 base 64 编码文件内容并被解码。

我经历了各种迭代和问题,包括导致 400 或 415 错误的变体,但据我所知,这些事情看起来应该排成一行。

更多数据点:

  Tomcat 10
  Jakarta 3.0.0
  Jersey 3.0.3 (and jersey media multipart 3.0.3)
  Java 8

任何建议将不胜感激。谢谢!

【问题讨论】:

  • 没有内置功能来检测base64数据并进行转换。在客户端,我认为它不应该自动将文件转换为 base64。你是在代码的某个地方做的吗?客户端的这个file 对象是什么?你是怎么创造出来的?
  • @PaulSamsotha 我已经编辑以显示我从哪里获得文件值(来自 imgSrc)。也许那是内存中的编码图像而不是原始内容?
  • readAsDataUrl 将其转换为 base64
  • @PaulSamsotha 谢谢!你是绝对正确的。通过缓存文件 (e.target.files[0]) 而不是对其进行编码。如果您想将此作为答案发布,我会接受。

标签: java rest jersey


【解决方案1】:

我想得到一个“真实的”(正确的问题和解决方案是什么)答案,但与此同时我又做了一个 hack:

InputStream outStream = hackBase64Decode(fileBody);
s3.putObject("mybucket", "pick_a_name", outStream, null);

    private InputStream hackBase64Decode(File fileBody) throws Exception
    {
        FileInputStream fs = new FileInputStream(fileBody);
        int ch;
        do {
            ch = fs.read();
        } while (ch != ',');
        return Base64.getDecoder().wrap(fs);
    }

可以说的最好的就是它有效。不过,还是希望得到一个真实的答案。

【讨论】:

    猜你喜欢
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 2014-09-03
    相关资源
    最近更新 更多