2
votes

I have angular2 front-end and Dropwizard back-end. I'm trying to upload a picture from front-end to back-end.

My html code:

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

My component:

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

My service:

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

My http interceptor:

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

The request is being send with such payload:

------WebKitFormBoundaryAz4AnN4lFPWKUvmH Content-Disposition: form-data; name="file"; filename="logo.png" Content-Type: image/png

------WebKitFormBoundaryAz4AnN4lFPWKUvmH--

And on my server I have:

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

Everything is fine, file is being saved, but it's saved with the whole request payload, including Content-Disposition, Content-Type headers, etc., and therefore the file becomes "broken".

How can I remove the Content-Disposition header from file?

1

1 Answers

2
votes

When you use an InputStream parameter, you're saying you want to whole request body. If you just want a single part, you need to annotate it with @FormDataParam with the name of the part

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
}

In order for this to work, you also need to to register the MutliPartFeature

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