1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-28 01:32:57 +01:00

Merge pull request #204 from svenstaro/master

Add Content-Disposition to NamedFile (fixes #172)
This commit is contained in:
Nikolay Kim 2018-04-29 08:18:48 -07:00 committed by GitHub
commit eb6e618812
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 8 deletions

View File

@ -14,7 +14,8 @@ use std::os::unix::fs::MetadataExt;
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use futures::{Async, Future, Poll, Stream}; use futures::{Async, Future, Poll, Stream};
use futures_cpupool::{CpuFuture, CpuPool}; use futures_cpupool::{CpuFuture, CpuPool};
use mime_guess::get_mime_type; use mime;
use mime_guess::{guess_mime_type, get_mime_type};
use error::Error; use error::Error;
use handler::{Handler, Reply, Responder, RouteHandler, WrapHandler}; use handler::{Handler, Reply, Responder, RouteHandler, WrapHandler};
@ -203,6 +204,18 @@ impl Responder for NamedFile {
let mut resp = HttpResponse::build(self.status_code); let mut resp = HttpResponse::build(self.status_code);
resp.if_some(self.path().extension(), |ext, resp| { resp.if_some(self.path().extension(), |ext, resp| {
resp.set(header::ContentType(get_mime_type(&ext.to_string_lossy()))); resp.set(header::ContentType(get_mime_type(&ext.to_string_lossy())));
}).if_some(self.path().file_name(), |file_name, resp| {
let mime_type = guess_mime_type(self.path());
let inline_or_attachment = match mime_type.type_() {
mime::IMAGE | mime::TEXT => "inline",
_ => "attachment",
};
resp.header(
"Content-Disposition",
format!("{inline_or_attachment}; filename={filename}",
inline_or_attachment=inline_or_attachment,
filename=file_name.to_string_lossy())
);
}); });
let reader = ChunkedReadFile { let reader = ChunkedReadFile {
size: self.md.len(), size: self.md.len(),
@ -251,12 +264,23 @@ impl Responder for NamedFile {
resp.if_some(self.path().extension(), |ext, resp| { resp.if_some(self.path().extension(), |ext, resp| {
resp.set(header::ContentType(get_mime_type(&ext.to_string_lossy()))); resp.set(header::ContentType(get_mime_type(&ext.to_string_lossy())));
}).if_some(self.path().file_name(), |file_name, resp| {
let mime_type = guess_mime_type(self.path());
let inline_or_attachment = match mime_type.type_() {
mime::IMAGE | mime::TEXT => "inline",
_ => "attachment",
};
resp.header(
"Content-Disposition",
format!("{inline_or_attachment}; filename={filename}",
inline_or_attachment=inline_or_attachment,
filename=file_name.to_string_lossy())
);
}).if_some(last_modified, |lm, resp| { }).if_some(last_modified, |lm, resp| {
resp.set(header::LastModified(lm)); resp.set(header::LastModified(lm));
}) }).if_some(etag, |etag, resp| {
.if_some(etag, |etag, resp| { resp.set(header::ETag(etag));
resp.set(header::ETag(etag)); });
});
if precondition_failed { if precondition_failed {
return Ok(resp.status(StatusCode::PRECONDITION_FAILED).finish()); return Ok(resp.status(StatusCode::PRECONDITION_FAILED).finish());
@ -589,7 +613,7 @@ mod tests {
use test::{self, TestRequest}; use test::{self, TestRequest};
#[test] #[test]
fn test_named_file() { fn test_named_file_text() {
assert!(NamedFile::open("test--").is_err()); assert!(NamedFile::open("test--").is_err());
let mut file = let mut file =
NamedFile::open("Cargo.toml").unwrap().set_cpu_pool(CpuPool::new(1)); NamedFile::open("Cargo.toml").unwrap().set_cpu_pool(CpuPool::new(1));
@ -602,11 +626,55 @@ mod tests {
} }
let resp = file.respond_to(HttpRequest::default()).unwrap(); let resp = file.respond_to(HttpRequest::default()).unwrap();
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/x-toml") assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/x-toml");
assert_eq!(
resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
"inline; filename=Cargo.toml"
);
} }
#[test] #[test]
fn test_named_file_status_code() { fn test_named_file_image() {
let mut file =
NamedFile::open("tests/test.png").unwrap().set_cpu_pool(CpuPool::new(1));
{
file.file();
let _f: &File = &file;
}
{
let _f: &mut File = &mut file;
}
let resp = file.respond_to(HttpRequest::default()).unwrap();
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "image/png");
assert_eq!(
resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
"inline; filename=test.png"
);
}
#[test]
fn test_named_file_binary() {
let mut file =
NamedFile::open("tests/test.binary").unwrap().set_cpu_pool(CpuPool::new(1));
{
file.file();
let _f: &File = &file;
}
{
let _f: &mut File = &mut file;
}
let resp = file.respond_to(HttpRequest::default()).unwrap();
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/octet-stream");
assert_eq!(
resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
"attachment; filename=test.binary"
);
}
#[test]
fn test_named_file_status_code_text() {
let mut file = NamedFile::open("Cargo.toml") let mut file = NamedFile::open("Cargo.toml")
.unwrap() .unwrap()
.set_status_code(StatusCode::NOT_FOUND) .set_status_code(StatusCode::NOT_FOUND)
@ -621,6 +689,10 @@ mod tests {
let resp = file.respond_to(HttpRequest::default()).unwrap(); let resp = file.respond_to(HttpRequest::default()).unwrap();
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/x-toml"); assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/x-toml");
assert_eq!(
resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
"inline; filename=Cargo.toml"
);
assert_eq!(resp.status(), StatusCode::NOT_FOUND); assert_eq!(resp.status(), StatusCode::NOT_FOUND);
} }

1
tests/test.binary Normal file
View File

@ -0,0 +1 @@
ÂTÇÉVù2þvI ª\ÇRË™ˆæeÞ<04>vDØ:è—½¬RVÖYpíÿ;ÍÏGñùp!2÷CŒ. <0C>û®õpA !ûߦÙx j+Uc÷±©X”c%Û;ï"yì­AI

BIN
tests/test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B