Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upload images #105

Closed
flosse opened this issue Jan 4, 2017 · 6 comments
Closed

upload images #105

flosse opened this issue Jan 4, 2017 · 6 comments
Labels
question A question (converts to discussion)

Comments

@flosse
Copy link

flosse commented Jan 4, 2017

How can I upload an image?
This is the form I use:

<form action="/admin/images/upload" method="post" enctype="multipart/form-data">
  <fieldset>
    <input name="file" type="file" accept="image/*">
    <input type="submit" value="upload">
  </fieldset>
</form>

Using a slightly modified code of the upload example form the docs:

#[post("/images/upload", format = "image/*", data = "<data>")]
pub fn upload(data: Data) -> io::Result<Redirect> {
    let path = env::temp_dir().join("upload");
    data.stream_to_file(path.clone())?;
    Ok(Redirect::to("/admin/images"))          
}

Results in a textfile like this:

------WebKitFormBoundaryn4rSHTBA207zcMWD
Content-Disposition: form-data; name="file"; filename="foo.jpg"
Content-Type: image/jpeg

ÿØÿà

So how can I access the filename and how can I stream the image itself?

@SergioBenitez
Copy link
Member

SergioBenitez commented Jan 4, 2017

Data gives you the raw data, as described in the documentation, but when you submit the form, the browser sends a multipart encoded body, not the raw data. The only way to get the browser to send the raw data is via JavaScript, as far as I know. The proper approach is to have your server-side code parse the multipart form structure (via a FromData type). Unfortunately Rocket itself doesn't provide such an implementation, but it should. I've opened #106 to track this.

The reasons Rocket doesn't provide an implementation yet are somewhat nuanced and predicated on the fact that everything is streamed: how do you validate the multipart form, which includes arbitrarily sized field, without reading it all? One approach is to demand that fields are always the last elements of the form structure if streaming is desired for the entire form. Another approach is to have a "maximum file upload" size and read the request into memory for validation. Yet another approach is to have types that specify what should happen with the file portions of a multipart form: a 'NamedFile' would automatically save the stream to a temporary file, and a handle would be given to the matching route. I believe this last approach is the way to go, but I haven't explored it in depth.

As a workaround, since your form is rather simple, you could implement a FromData type that minimally parses the form and returns a handle to the filename and stream beginning at the file's contents.

@SergioBenitez SergioBenitez added the question A question (converts to discussion) label Jan 4, 2017
@flosse
Copy link
Author

flosse commented Jan 4, 2017

As a workaround, since your form is rather simple, you could implement a FromData type that minimally parses the form and returns a handle to the filename and stream beginning at the file's contents.

Could you help me?

@SergioBenitez
Copy link
Member

Handling this out-of-band.

@flosse
Copy link
Author

flosse commented Jan 5, 2017

I just saw that I can grab the boundary information since 2da08a9 :)
I tried this:

let mut mp = Multipart::with_body(data.open(), content_type.params.unwrap().string); 
let entries = mp.save_all().to_entries().unwrap();
debug!("entries: {:?}", entries);

But this doesn't work :( There are no entries :(

@flosse
Copy link
Author

flosse commented Jan 5, 2017

Now I know my mistake: I have to remove the boundary= from the params string :)

@jparr721
Copy link

@flosse did you figure out the multipart? If so, would you be willing to share your code? I have been trying to figure this out for days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question A question (converts to discussion)
Projects
None yet
Development

No branches or pull requests

3 participants