Amazon s3 如何在Amazon';s S3
如果我在Amazon的S3上有现有文件,那么不必下载文件就可以获得md5sum的最简单方法是什么Amazon s3 如何在Amazon';s S3,amazon-s3,Amazon S3,如果我在Amazon的S3上有现有文件,那么不必下载文件就可以获得md5sum的最简单方法是什么 谢谢对于多部分上传,ETag似乎不是MD5(根据Gael Fraiteur的评论)。在这些情况下,它包含一个减号后缀和一个数字。然而,即使减号之前的位似乎也不是MD5,尽管它的长度与MD5相同。后缀可能是上传的部件数量?我已经对照上传文件的MD5sum交叉检查了jets3t和管理控制台,ETag似乎等于MD5sum。您可以在AWS管理控制台中查看文件的属性: 这对我很有用。 在PHP中,您可以使用以
谢谢对于多部分上传,ETag似乎不是MD5(根据Gael Fraiteur的评论)。在这些情况下,它包含一个减号后缀和一个数字。然而,即使减号之前的位似乎也不是MD5,尽管它的长度与MD5相同。后缀可能是上传的部件数量?我已经对照上传文件的MD5sum交叉检查了jets3t和管理控制台,ETag似乎等于MD5sum。您可以在AWS管理控制台中查看文件的属性: 这对我很有用。 在PHP中,您可以使用以下方法比较本地文件和amazon文件之间的校验和:
// get localfile md5
$checksum_local_file = md5_file ( '/home/file' );
// compare checksum between localfile and s3file
public function compareChecksumFile($file_s3, $checksum_local_file) {
$Connection = new AmazonS3 ();
$bucket = amazon_bucket;
$header = $Connection->get_object_headers( $bucket, $file_s3 );
// get header
if (empty ( $header ) || ! is_object ( $header )) {
throw new RuntimeException('checksum error');
}
$head = $header->header;
if (empty ( $head ) || !is_array($head)) {
throw new RuntimeException('checksum error');
}
// get etag (md5 amazon)
$etag = $head['etag'];
if (empty ( $etag )) {
throw new RuntimeException('checksum error');
}
// remove quotes
$checksumS3 = str_replace('"', '', $etag);
// compare md5
if ($checksum_local_file === $checksumS3) {
return TRUE;
} else {
return FALSE;
}
}
对于那些花时间四处搜索以找出md5为何与S3中的ETag不同的人来说 ETag将根据chuck of data和concat all md5hash进行计算,以再次生成md5 hash,并将区块数保留在最后 下面是生成哈希的C#版本
string etag = HashOf("file.txt",8);
源代码
private string HashOf(string filename,int chunkSizeInMb)
{
string returnMD5 = string.Empty;
int chunkSize = chunkSizeInMb * 1024 * 1024;
using (var crypto = new MD5CryptoServiceProvider())
{
int hashLength = crypto.HashSize/8;
using (var stream = File.OpenRead(filename))
{
if (stream.Length > chunkSize)
{
int chunkCount = (int)Math.Ceiling((double)stream.Length/(double)chunkSize);
byte[] hash = new byte[chunkCount*hashLength];
Stream hashStream = new MemoryStream(hash);
long nByteLeftToRead = stream.Length;
while (nByteLeftToRead > 0)
{
int nByteCurrentRead = (int)Math.Min(nByteLeftToRead, chunkSize);
byte[] buffer = new byte[nByteCurrentRead];
nByteLeftToRead -= stream.Read(buffer, 0, nByteCurrentRead);
byte[] tmpHash = crypto.ComputeHash(buffer);
hashStream.Write(tmpHash, 0, hashLength);
}
returnMD5 = BitConverter.ToString(crypto.ComputeHash(hash)).Replace("-", string.Empty).ToLower()+"-"+ chunkCount;
}
else {
returnMD5 = BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", string.Empty).ToLower();
}
stream.Close();
}
}
return returnMD5;
}
AWS关于ETag的文件规定: 实体标记是对象的散列。ETag只反映对象内容的更改,而不反映其元数据。ETag可能是也可能不是对象数据的MD5摘要。是否是取决于对象是如何创建的,以及它是如何按照如下所述进行加密的:
- 由PUT对象、POST对象或复制操作创建的对象,或通过AWS管理控制台创建的对象,并由SSE-S3或明文加密,其ETag是其对象数据的MD5摘要
- 由PUT对象、POST对象或复制操作创建的对象,或通过AWS管理控制台创建的对象,并由SSE-C或SSE-KMS加密,其ETag不是其对象数据的MD5摘要
- 如果通过多部分上载或部分复制操作创建对象,则无论采用何种加密方法,ETag都不是MD5摘要
参考资料:以下是根据2017获取MD5哈希的代码
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Base64;
public class GenerateMD5 {
public static void main(String args[]) throws Exception{
String s = "<CORSConfiguration> <CORSRule> <AllowedOrigin>http://www.example.com</AllowedOrigin> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration>";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(s.getBytes());
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
/*for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}*/
System.out.println(sb.toString());
StringBuffer sbi = new StringBuffer();
byte [] bytes = Base64.encodeBase64(digest);
String finalString = new String(bytes);
System.out.println(finalString);
}
}
import java.security.MessageDigest;
导入java.security.NoSuchAlgorithmException;
导入org.apache.commons.codec.binary.Base64;
公共类生成器D5{
公共静态void main(字符串args[])引发异常{
字符串s=”http://www.example.com 将帖子删除*3000*获取*3000”;
MessageDigest md=MessageDigest.getInstance(“MD5”);
md.update(s.getBytes());
字节[]摘要=md.digest();
StringBuffer sb=新的StringBuffer();
/*for(字节b:摘要){
sb.append(字符串格式(“%02x”,b&0xff));
}*/
System.out.println(sb.toString());
StringBuffer sbi=新的StringBuffer();
byte[]bytes=Base64.encodeBase64(摘要);
字符串finalString=新字符串(字节);
系统输出打印LN(最终打印);
}
}
注释代码是大多数人错误的地方,将其更改为十六进制以下是获取PowerShell中从c#转换的对象的S3 ETag的代码 我发现s3cmd有一个--list-md5选项,可以与ls命令一起使用,例如
s3cmd ls --list-md5 s3://bucket_of_mine/
希望这有帮助。最简单的方法是在将这些文件上载到bucket之前,将校验和设置为元数据:
ObjectMetadata md=newObjectMetadata();
md.setContentMD5(“foobar”);
PutObjectRequest req=新的PutObjectRequest(BUCKET、KEY、新文件(“/path/to/File”))。带有元数据(md);
tm.upload(req.waitForUploadResult();
现在,您无需下载文件即可访问这些元数据:
ObjectMetadata md2=s3Client.getObjectMetadata(BUCKET,KEY);
System.out.println(md.getContentMD5());
来源:下面是我比较本地文件校验和与s3 etag的工作。 我用的是Python def md5_校验和(文件名): m=hashlib.md5() 将open(filename,'rb')作为f: 对于iter中的数据(λ:f.read(1024*1024),b''): m、 更新(数据) 返回m.hexdigest() def etag_校验和(文件名,块大小=8*1024*1024): md5s=[] 将open(filename,'rb')作为f: 对于iter中的数据(lambda:f.read(块大小),b''): append(hashlib.md5(data.digest()) m=hashlib.md5(b.)。加入(md5s)) 打印(“{}-{}.”格式(m.hexdigest(),len(md5s))) 返回'{}-{}'。格式(m.hexdigest(),len(md5s)) def etag_比较(文件名,etag): et=etag[1:-1]#带引号 打印('et',et) 如果et中的“-”和et==etag_校验和(文件名): 返回真值 如果“-”不在et中且et==md5_校验和(文件名): 返回真值 返回错误 def main(): session=bot3.session( aws\u访问密钥\u id=s3\u访问密钥, aws_secret_access_key=s3_secret ) s3=会话。客户端('s3') obj_dict=s3.get_对象(Bucket=Bucket\u name,Key=your\u Key) etag=(obj_dict['etag']) 打印('etag',etag) 验证=etag\u比较(文件名,etag) 打印(验证) etag_校验和(文件名,块大小=8*1024*1024)
返回验证这是一个非常老的问题,但我很难找到下面的信息,这是我能找到的第一个地方,所以我想详细说明一下,以防有人需要 ETag是MD5。但是对于多部分上传的文件,MD5是从每个上传部分的MD5的串联计算出来的。 因此,您不需要在服务器中计算MD5。只要拿到ETag就行了 正如@EmersonFarrugia在回答时所说: 假设你上传了一个14MB的文件,你的部件大小是5MB。计算每个部分对应的3个MD5校验和,即前5MB、第二5MB和最后4MB的校验和。然后取它们连接的校验和。由于MD5校验和是二进制数据的十六进制表示形式,因此只需确保采用解码二进制级联的MD5,而不是ASCII或UTF-8编码级联的MD5
s3cmd ls --list-md5 s3://bucket_of_mine/
#!/bin/bash
set -euo pipefail
if [ $# -ne 2 ]; then
echo "Usage: $0 file partSizeInMb";
exit 0;
fi
file=$1
if [ ! -f "$file" ]; then
echo "Error: $file not found."
exit 1;
fi
partSizeInMb=$2
fileSizeInMb=$(du -m "$file" | cut -f 1)
parts=$((fileSizeInMb / partSizeInMb))
if [[ $((fileSizeInMb % partSizeInMb)) -gt 0 ]]; then
parts=$((parts + 1));
fi
checksumFile=$(mktemp -t s3md5.XXXXXXXXXXXXX)
for (( part=0; part<$parts; part++ ))
do
skip=$((partSizeInMb * part))
$(dd bs=1M count=$partSizeInMb skip=$skip if="$file" 2> /dev/null | md5sum >> $checksumFile)
done
etag=$(echo $(xxd -r -p $checksumFile | md5sum)-$parts | sed 's/ --/-/')
echo -e "${1}\t${etag}"
rm $checksumFile
#!/bin/bash
if [ $# -ne 2 ]; then
echo "Usage: $0 file partSizeInMb";
exit 0;
fi
file=$1
if [ ! -f "$file" ]; then
echo "Error: $file not found."
exit 1;
fi
partSizeInMb=$2
fileSizeInMb=$(du -m "$file" | cut -f 1)
parts=$((fileSizeInMb / partSizeInMb))
if [[ $((fileSizeInMb % partSizeInMb)) -gt 0 ]]; then
parts=$((parts + 1));
fi
checksumFile=$(mktemp -t s3md5)
for (( part=0; part<$parts; part++ ))
do
skip=$((partSizeInMb * part))
$(dd bs=1m count=$partSizeInMb skip=$skip if="$file" 2>/dev/null | md5 >>$checksumFile)
done
echo $(xxd -r -p $checksumFile | md5)-$parts
rm $checksumFile