【问题标题】:File is being saved with Content-Disposition header正在使用 Content-Disposition 标头保存文件
【发布时间】:2017-09-05 09:08:29
【问题描述】:

我有 angular2 前端和 Dropwizard 后端。我正在尝试将图片从前端上传到后端。

我的html代码:

<input type="file" name="file" (change)="fileChange($event)">

我的组件:

fileChange(event) {
    let fileList: FileList = event.target.files;
    if (fileList.length > 0) {
        let file: File = fileList[0];
        let formData:FormData = new FormData();
        formData.append('file', file);
        this.siteDescriptionService.sendPhoto(formData).subscribe(value => {
            console.log("value", value);
        });
    }
}

我的服务:

sendPhoto(data): Observable<any> {
    return this.http.postPhoto('api/site/savePhoto', data, null).map(res => res);
}

我的 http 拦截器:

postPhoto(url: string, params?: any, options?: RequestOptionsArgs): Observable<any> {
    this.beforeRequest();
    let headers = new Headers();
    headers.append('Content-Type', 'multipart/form-data');
    let reqOptions = new RequestOptions({ headers: headers });
    return super.post(this.getFullUrl(url), params, reqOptions)
        .catch(this.onCatch)
        .do((res: Response) => {
            this.onSuccess(res);
        }, (error: any) => {
            this.onError(error);
        })
        .finally(() => {
            this.onFinally();
        });
}

正在使用这样的负载发送请求:

------WebKitFormBoundaryAz4AnN4lFPWKUvmH 内容处置:表单数据;名称=“文件”;文件名="logo.png" 内容类型:image/png

-----WebKitFormBoundaryAz4AnN4lFPWKUvmH--

在我的服务器上我有:

@POST
@Timed
@Path("savePhoto")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public Response uploadFile(InputStream uploadedInputStream) throws IOException {
    String uploadedFileLocation = "/tmp/photo1.png";


    FormDataMultiPart part = new FormDataMultiPart().field("file", uploadedInputStream, MediaType.TEXT_PLAIN_TYPE);

    FormDataBodyPart p = part.getField("file");
    InputStream i = (InputStream) p.getEntity();

    writeToFile( i, uploadedFileLocation);

    String output = "File uploaded to : " + uploadedFileLocation;
    return Response.ok(output).build();
}

private void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation)
        throws IOException {
    int read;
    final int BUFFER_LENGTH = 1024;
    final byte[] buffer = new byte[BUFFER_LENGTH];
    OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
    while ((read = uploadedInputStream.read(buffer)) != -1) {
        out.write(buffer, 0, read);
    }
    out.flush();
    out.close();
}

一切正常,正在保存文件,但它与整个请求负载一起保存,包括Content-DispositionContent-Type 标头等,因此文件“损坏”。

如何从文件中删除 Content-Disposition 标头?

【问题讨论】:

    标签: java angular multipartform-data dropwizard


    【解决方案1】:

    当您使用InputStream 参数时,您是在说您想要整个请求正文。如果你只想要一个零件,你需要用@FormDataParam注释它并带有零件的名称

    public Response uploadFile(@FormDataParam("file") InputStream file,
                               @FormDataParam("file") FormDataContentDisposition fdcd) {
        String filename = fcdc.getFileName();
    
        // You don't need to create the FormDataMultiPart
        // just save the InputStream parameter
    }
    

    为了使其工作,您还需要注册MutliPartFeature

    env.jersey().register(MultiPartFeature.class);
    

    【讨论】:

    • 我试过了,但是 Jersey(如果我做对了)返回 400 错误。
    • 这意味着这是一个客户端错误。使用 JS 客户端时,不应在客户端上将 Content-Type 标头设置为 multipart/form-date。通过这样做,您没有边界,这会导致泽西岛拒绝它。您应该让浏览器创建标头值。我认为您可以通过将 Content-Tpye 标头值设置为未定义来做到这一点。如果这不起作用,请搜索如何使用 Angular 发送文件。答案应提及此问题并提供正确的方法
    • 我试过没有 Content-Type: multipart/form-data,但它也不起作用。我google了很多,但没有找到任何解决方案。我不得不为此创建额外的 servlet,并且它运行良好(是的,我从客户端发送图片而没有 multipart/form-data 标头)。但我仍然对这种方法非常感兴趣。
    • 当我删除标题时,会出现边界。浏览器添加:Content-Type:multipart/form-data;边界=----WebKitFormBoundary1uqVbHzzENKo4azE
    • 如果它使用 Servlet API 工作,我不明白为什么它不能与 Jersey 工作。你确定结果还是400?什么是确切的错误信息。应该有一个返回。甚至在服务器上记录一个错误。
    猜你喜欢
    • 1970-01-01
    • 2015-05-12
    • 2012-02-27
    • 2010-11-03
    • 2022-07-06
    • 2011-02-02
    • 1970-01-01
    • 2016-12-09
    相关资源
    最近更新 更多