zoukankan      html  css  js  c++  java
  • Rust-HayStack

    安装rust

    curl https://sh.rustup.rs -sSf | sh

    建立项目

    cargo new upfile

    编写图片服务器 

    src/main.rs 

    extern crate multipart;
    extern crate iron;
    extern crate time;
    //image converter
    extern crate image;
    extern crate crypto;
    extern crate rustc_serialize;
    use rustc_serialize::json;
    
    use crypto::md5::Md5;
    use crypto::digest::Digest;
    
    use std::fs::File;
    use std::io::Read;
    use std::path::Path;
    use multipart::server::{Multipart, Entries, SaveResult};
    
    use iron::prelude::*;
    use iron::status;
    use iron::mime::Mime;
    
    extern crate router;
    use router::Router;
    
    const INDEX_HTML: &'static [u8] = include_bytes!("../index.html");
    
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    struct JsonResult  {
        ret: bool,
        data: String,
    }
    
    fn main() {
        let mut router = Router::new();
    
        router.get("/", | _: &mut Request| {
            let content_type = "text/html".parse::<Mime>().unwrap();
            Ok(Response::with((content_type, status::Ok, INDEX_HTML)))
        });
        router.post("upload", process_upload);
        //04fd905e6e449e50f9bf5095960bdb54
        router.get("/:md5", process_query);
    
        router.get("error", |_: &mut Request| {
          Ok(Response::with(status::BadRequest))
        });
    
        Iron::new(router).http("0.0.0.0:8080").unwrap();
    
        // Iron::new(process_upload).http("localhost:8080").expect("Could not bind localhost:8080");
    }
    ///process query
    fn process_query(request: &mut Request) -> IronResult<Response> {
       let ref md5 = request.extensions.get::<Router>().unwrap().find("md5").unwrap_or("/");
       let content_type = "image/jpeg".parse::<Mime>().unwrap();
       let img = match image::open(format!("{}.jpg",md5)) {
           Ok(img) => img,
           Err(e) => return Err(IronError::new(e, status::InternalServerError))
       };
    
       // let thumb = img.resize(128, 128, image::FilterType::Triangle);
       let mut buffer = vec![];
    
       match img.save(&mut buffer, image::JPEG) {
           Ok(_) => Ok(Response::with((content_type,iron::status::Ok, buffer))),
           Err(e) => Err(IronError::new(e, status::InternalServerError))
       }
    }
    
    /// Processes a request and returns response or an occured error.
    fn process_upload(request: &mut Request) -> IronResult<Response> {
        // Getting a multipart reader wrapper
        match Multipart::from_request(request) {
            Ok(mut multipart) => {
                // Fetching all data and processing it.
                // save_all() reads the request fully, parsing all fields and saving all files
                // in a new temporary directory under the OS temporary directory.
                match multipart.save_all() {
                    SaveResult::Full(entries) => process_entries(entries),
                    SaveResult::Partial(entries, error) => {
                        try!(process_entries(entries));
                        Err(IronError::new(error, status::InternalServerError))
                    }
                    SaveResult::Error(error) => Err(IronError::new(error, status::InternalServerError)),
                }
            }
            Err(_) => {
                Ok(Response::with((status::BadRequest, "The request is not multipart")))
            }
        }
    }
    
    /// Processes saved entries from multipart request.
    /// Returns an OK response or an error.
    fn process_entries(entries: Entries) -> IronResult<Response> {
        let mut md5s = String::new();
        for (name, field) in entries.fields {
            println!(r#"Field "{}": "{}""#, name, field);
        }
    
        for (name, savedfile) in entries.files {
            let filename = match savedfile.filename {
                Some(s) => s,
                None => "None".into(),
            };
            let file_start = time::now();
            let mut file = match File::open(savedfile.path) {
                Ok(file) => file,
                Err(error) => {
                    return Err(IronError::new(error,
                                              (status::InternalServerError,
                                               "Server couldn't save file")))
                }
            };
            let file_end = time::now();//
            println!("file load!start : {},end :{},duration:{}",file_start.rfc3339(),file_end.rfc3339(),file_end-file_start);
            //caculate md5
            let mut buffer = Vec::new();
            // read the whole file
            file.read_to_end(&mut buffer).unwrap();
            let mut hasher = Md5::new();
            hasher.input(&buffer);
            let md5 = hasher.result_str();
            // println!("{}", md5);
            md5s = md5s + &md5 + ",";
            let md5_end = time::now();//
            println!("md5 load!start : {},end :{},duration:{}",file_end.rfc3339(),md5_end.rfc3339(),md5_end-file_end);
            //image file
            let img = match image::load_from_memory(&buffer){
                Ok(file) => file,
                Err(error) => {
                    return Err(IronError::new(error,
                                              (status::InternalServerError,
                                               "Unsupported image format")))
                }
            };
            let img_end = time::now();//
            println!("img load!start : {},end :{},duration:{}",md5_end.rfc3339(),img_end.rfc3339(),img_end-md5_end);
    
            let ref mut fout = File::create(&Path::new(&*(md5+".jpg"))).unwrap();
            // The dimensions method returns the images width and height
            // println!("dimensions {:?}", img.dimensions());
            // The color method returns the image's ColorType
            // println!("{:?}", img.color());
    
            // Write the contents of this image to the Writer in PNG format.
            let _ = img.save(fout, image::JPEG).unwrap();
    
            let save_end = time::now();//
            println!("save file!start : {},end :{},duration:{}",img_end.rfc3339(),save_end.rfc3339(),save_end-img_end);
    
            println!(r#"Field "{}" is file "{}":"#, name, filename);
        }
        let content_type = "application/json".parse::<Mime>().unwrap();
        let object = JsonResult{
            ret:true,
            data:md5s,
        };
        Ok(Response::with((content_type, status::Ok, json::encode(&object).unwrap())))
        // Ok(Response::with((status::Ok, md5s)))
    }

    index.html

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <html>
        <head>
            <script>
                var totals = 1;
                function addInput()
                {
                    var newItemText=document.createTextNode("Choose file:");
                    var newItemInput=document.createElement("input");
                    newItemInput.name="userfile"+(totals++);
                    newItemInput.type="file";
                    var addfile=document.getElementById("bt_addfile");
                    var submit=document.getElementById("bt_submit");
                    var newItemBr=document.createElement("br");
    
                    var myform=document.getElementById("upform");
                    myform.appendChild(newItemText);
                    myform.appendChild(newItemInput);
                    myform.appendChild(addfile);
                    myform.appendChild(newItemBr);
                    myform.appendChild(submit);
                }
            </script>
        </head>
        <h1>Welcome to images' World!</h1>
        <p>Upload image(s) to server:</p>
        <form enctype="multipart/form-data" action="/upload" method=post target=_blank id="upform">
            Choose file:<input name="userfile" type="file">
            <input type="button" value="+" onclick="addInput()" id="bt_addfile">
            </br>
            <input type="submit" value="upload" id="bt_submit">
        </form>
    </html>

    Cargo.toml

    [package]
    name = "upfile"
    version = "0.1.0"
    authors = ["mignet <mignetwee@gmail.com>"]

    [dependencies]
    iron = "0.2"
    image = "*"
    time = "*"
    router = "*"
    rustc-serialize = "*"
    rust-crypto = "0.2.35"

    [dependencies.multipart]
    version = "0.5.1"
    default-features = false
    features = ["server", "iron"]

    性能测试:

    mignet@Master:~/rust-projects/upfile$ cargo run
       Compiling upfile v0.1.0 (file:///home/mignet/rust-projects/upfile)
         Running `target/debug/upfile`
    file load!start : 2016-04-17T16:00:49+08:00,end :2016-04-17T16:00:49+08:00,duration:PT0.000094890S
    md5 load!start : 2016-04-17T16:00:49+08:00,end :2016-04-17T16:00:49+08:00,duration:PT0.023411631S
    img load!start : 2016-04-17T16:00:49+08:00,end :2016-04-17T16:00:52+08:00,duration:PT2.621793752S
    save file!start : 2016-04-17T16:00:52+08:00,end :2016-04-17T16:00:55+08:00,duration:PT3.651583434S
    Field "userfile" is file "StarUml.png":
    ---------------------------------------------------------------
    mignet@Master:~/rust-projects/upfile$ cargo run --release
       Compiling upfile v0.1.0 (file:///home/mignet/rust-projects/upfile)
         Running `target/release/upfile`
    file load!start : 2016-04-17T16:02:28+08:00,end :2016-04-17T16:02:28+08:00,duration:PT0.000099016S
    md5 load!start : 2016-04-17T16:02:28+08:00,end :2016-04-17T16:02:28+08:00,duration:PT0.001155275S
    img load!start : 2016-04-17T16:02:28+08:00,end :2016-04-17T16:02:28+08:00,duration:PT0.055703035S
    save file!start : 2016-04-17T16:02:28+08:00,end :2016-04-17T16:02:28+08:00,duration:PT0.375560153S
    Field "userfile" is file "StarUml.png":

      部署访问地址:http://images.v5ent.com

  • 相关阅读:
    Django model转字典的几种方法
    使用Nagios打造专业的业务状态监控
    Etcd安全配置之Basic Auth认证
    ELK日志系统之通用应用程序日志接入方案
    ELK日志系统之使用Rsyslog快速方便的收集Nginx日志
    中小团队落地配置中心详解
    ELK构建MySQL慢日志收集平台详解
    Django model select的各种用法详解
    Python:每日一题003
    Python:每日一题002
  • 原文地址:https://www.cnblogs.com/mignet/p/Rust_HayStack.html
Copyright © 2011-2022 走看看