Let's look at this piece by piece:
let path = std::path::Path::new(&file);
If you have a look at the documentation for Path::new, you see the following signature:
pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path
After applying the second lifetime elision rules, (quote: "if there is exactly one input lifetime parameter, that lifetime is assigned to all output lifetime parameters: fn foo<'a>(x: &'a i32) -> &'a i32"), this signature really looks like this:
pub fn new<'a, S: AsRef<OsStr> + ?Sized>(s: &'a S) -> &'a Path
So, your path variable cannot live longer than your file variable.
Next, this is relevant:
.file_name(path.file_name().unwrap().to_string_lossy())
After again applying the lifetime elision rules, you can see that calling unwrap on path.file_name() gives you a &std::ffi::OsStr that can live no longer than your path variable which in turn (as discussed before) can live no longer than your file variable. So, transitively, path.filename().unwrap() can live no longer than the file variable.
Now, let's have a look at the signature of OsStr::to_string_lossy():
pub fn to_string_lossy(&self) -> Cow<'_, str>
So, this method returns a Cow<'_, str>. Cow is shorthand for "Copy or Owned" – meaning that the Cow can either contain a reference to the data (in this case, a &str, if the OsStr contained only valid UTF-8 bytes) or it can own the data itself (in this case, by containing a String, if the OsStr contained data that needed to be converted or to be filtered out during UTF-8 conversion).
'_ is a placeholder and means that the compiler shall (again) infer the lifetime with the lifetime elision rules. The expanded signature looks like this:
pub fn to_string_lossy<'a>(&'a self) -> Cow<'a, str>
So, in your example, 'a can't be any bigger than the lifetime of your &OsStr returned by unwrap(), which transitively means that 'a can't be bigger than the lifetime of file.
However, reqwest::multipart::Part::file_name() expects something implementing Into<Cow<'static, str>> as parameter. Our Cow<'a, str> definitively can't implement that, as our file variable is not alive until the end of the program. If it was alive until the end of the program, our Cow would implement it because file could be borrowed for 'static, and all would be well – this is the reason for the error message.
You can work around this by calling into_owned() on the Cow. This converts the Cow into a string, which does implement Into<Cow<'static, str>>:
use rand::prelude::*;
fn getFiles(dirname: &str) -> Vec<String> {
let mut items: Vec<String> = Vec::new();
let dir = std::fs::read_dir(dirname);
for item in dir.expect("fail") {
if let Ok(item) = item {
items.push(item.path().into_os_string().into_string().unwrap());
}
}
items
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// call the function
let dir_items = getFiles("src/assets");
let file = dir_items.into_iter().choose(&mut rand::thread_rng()).unwrap();
let path = std::path::Path::new(&file);
let sub_file = std::fs::read(path)?;
// after this, file lifetime is already end ?
let sub_file_part = reqwest::multipart::Part::bytes(sub_file)
.file_name(path.file_name().unwrap().to_string_lossy().into_owned())
.mime_str("application/octet-stream")?;
Ok(())
}
Playground