Rust:如何对大文件进行 HTTP PUT?

标签 rust

在 Rust 中,我使用 ureq执行 HTTP 请求。这是一个有效的 HEAD 请求:

let resp = ureq::head(&url).timeout_connect(5_000).call();
if !resp.ok() {
    return false;
}

我看到 ureq supports动词 PUT,pub fn put(path: &str) -> Request 只是不确定如何使用它。如何向其传递文件/文件句柄/完整路径?

这是我在 bash 中执行此操作的方法:

$ curl -v http://192.168.1.100:9193/  -T deleteme.mp4
* Expire in 0 ms for 6 (transfer 0x1102880)
*   Trying 192.168.1.100...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x1102880)
* Connected to 192.168.1.100 (192.168.1.100) port 9193 (#0)
> PUT /deleteme.mp4 HTTP/1.1
> Host: 192.168.1.100:9193
> User-Agent: curl/7.64.0
> Accept: */*
> Content-Length: 779189
> Expect: 100-continue
>
* Expire in 1000 ms for 0 (transfer 0x1102880)
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Date: Fri, 03 Jan 2020 23:57:41 GMT
< Content-Length: 0
<
* Connection #0 to host 192.168.1.100 left intact

$ curl -I http://192.168.1.100:9193/deleteme.mp4
HTTP/1.1 200 OK
Content-Length: 779189
Date: Fri, 03 Jan 2020 23:57:44 GMT

编辑 1

由于我的文件很大,我无法将其全部读入内存(耗尽),而是需要 bufio reader 之类的东西。下面是我尝试的代码,但它失败了。在接收器上创建一个空文件。

响应[状态:500,status_text:网络错误] PUT deleteme.mp4 写入:0 字节,花费:70.4μs

use std::error::Error;
use std::fs::File;
use std::io::{BufRead, BufReader};

const FILE_NAME: &str = "/tmp/deleteme.mp4";

fn main() -> Result<(), Box<dyn Error>> {
    println!("Hello, world!");
    let f = File::open(FILE_NAME)?;
    let mut buffered_reader = BufReader::new(f);
    let r = ureq::put("http://192.168.1.100:9193/deleteme.mp4").send(buffered_reader);
    println!("{:?}", r);

    println!("Bye!");

    Ok(())
}

如何使 BufReaderureq 之间的管道工作?

最佳答案

对于具有非空正文的 HTTP 请求,您必须设置 Content-LengthTransfer-Encoding header 。例如,您的curl session 中有一个Content-Length header 。

ureq::Request::send_bytesureq::Request::send_string将为您设置此 header ,但是 ureq::Request::send惯于。你必须自己做:

use std::error::Error;
use std::fs::File;
use std::io::BufReader;

fn main() -> Result<(), Box<dyn Error>> {
    let f = File::open("/tmp/deleteme.mp4")?;
    let metadata = f.metadata()?;
    let buffered_reader = BufReader::new(f);
    let r = ureq::put("http://192.168.1.100:9193/deleteme.mp4")
        .set("Content-Length", &metadata.len().to_string())
        .send(buffered_reader);
    println!("{:?}", r);

    Ok(())
}

关于Rust:如何对大文件进行 HTTP PUT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59586787/

相关文章:

enums - 特征可以用于枚举类型吗?

rust - Cargo init 像 cargo new 一样创建新目录

rust - 如何在选项中引用特征对象?

rust - 没有显式返回的关联函数是错误的[E0308] : mismatched types

rust - 二维旋转

rust - 为什么 cargo build 不能提供丰富多彩的错误信息?

rust - 为什么运行时实现者应该避免枚举链上的 EnumerableStorageMap 存储条目?

rust - 字符串切片vs切片&String

rust - 如何仅将自定义序列化用于 “stringy”序列化?

rust - 尝试在Wasm堆中保存字符串,然后将指向该字符串的指针保存在结构中时,使用“RuntimeError : Memory access out of bounds”