Во-первых, извините за длинный заголовок.Rust AWS API Gateway Service Proxy для загрузки S3-файла с использованием необработанного запроса https
Я установил шлюз api для работы в качестве прокси-сервера s3, чтобы я мог загружать файлы, отправив запрос PUT на api url. Api работает отлично (или, по крайней мере, я думаю, что это так), но кажется, что я могу загружать только текстовые файлы.
Для загруженных текстовых файлов (например, Content-Type = text/plain) размеры локальных файлов идентичны размерам файлов, загружаемых в ведро s3. НО, это не относится к двоичным файлам (например, Content-Type = application/pdf). Файлы в ведрах s3 имеют больший размер. Когда я загружаю двоичные файлы из s3, я не могу их открыть, они повреждены.
Вот ржавчина код, чтобы отправить запрос, я использую hyper's http client:
match File::open(file.as_path()) {
Err(_) => Err("Failed to open file".to_owned()),
Ok(mut openned_file) => {
let file_mime = mime_guess::guess_mime_type(file.as_path());
let connector = HttpsConnector::new(OpensslClient::default());
let url_str = format!("https://my.api.com/upload/{}",
file.file_name().unwrap().to_str().unwrap());
let mut client =
Request::with_connector(Method::Put, Url::parse(&url_str).unwrap(), &connector)
.unwrap();
client.headers_mut().set(ContentType(file_mime.clone()));
// client.headers_mut().set(ContentLength(openned_file.metadata().unwrap().len()));
let file_mime_str = file_mime.to_string();
let mut buffer: [u8; 4096] = [0; 4096];
let mut uploaded: usize = 0;
let request = match file_mime {
Mime(TopLevel::Text, _, _) |
Mime(TopLevel::Application, SubLevel::Javascript, _) => {
let mut request = client.start().unwrap();
println!("Uploading text ...",);
while let Ok(read_count) = openned_file.read(&mut buffer) {
if read_count > 0 {
println!("Uploading {} bytes", read_count);
request.write_all(&buffer[0..read_count]);
uploaded += read_count;
} else {
request.flush();
println!("File mime: {}", file_mime_str);
println!("File size: {}, Total uploaded: {}",
openned_file.metadata().unwrap().len(),
uploaded);
break;
}
}
request
}
_ => {
// client.headers_mut()
// .set_raw("Content-Encoding", vec![b"base64".to_vec()]);
let mut request = client.start().unwrap();
let mut config = MIME;
config.line_length = None;
println!("Uploading binary ...",);
while let Ok(read_count) = openned_file.read(&mut buffer) {
if read_count > 0 {
println!("Uploading {} bytes", read_count);
request.write_all(&buffer[0..read_count]);
// let base64_str = buffer[0..read_count].to_base64(STANDARD);
// request.write_all(base64_str.into_bytes().as_slice());
uploaded += read_count;
} else {
request.flush();
println!("File mime: {}", file_mime_str);
println!("File size: {}, Total uploaded: {}",
openned_file.metadata().unwrap().len(),
uploaded);
break;
}
}
request
}
};
match request.send() {
Err(err) => Err(format!("{}", err)),
Ok(mut response) => {
let mut rep_str = String::new();
response.read_to_string(&mut rep_str);
Err(format!("{}", rep_str))
}
}
Как вы можете видеть из закомментированного кода, я попытался с помощью Content-Encoding = base64 и кодирование байты, считанные из файла для загрузки. Но Content-Encoding = base64 кажется недействительным типом кодировки, который принимает s3. Я не смог полностью загрузить (500: Внутренняя ошибка сервера, я даже не вижу файл с неправильным размером в ведро s3), когда я устанавливаю Content-Encoding. Но текстовый файл работает отлично.
Для справки:
- http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
- https://developer.salesforce.com/forums/?id=906F0000000BMDFIA4