- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如何在调用 blob.upload(new FileInputStream(imageFile), imageFile.length());
后打印已上传的字节数?我想记录类似“已上传 100/totalBytes 字节,已上传 224/totalBytes 字节...”之类的内容,因此我可以创建上传进度的进度条。
这是代码:
//AzureBlobLoader 扩展 AsyncTask
public class AzureBlobUploader extends AzureBlobLoader {
private Activity act;
private String userName;
private TaggedImageObject img;
private Fragment histFragment;
public AzureBlobUploader(Fragment f, Activity act, String userName, TaggedImageObject img) {
super();
this.act = act;
this.userName = userName;
this.img = img;
this.histFragment = f;
}
@Override
protected Object doInBackground(Object[] params) {
File imageFile = new File(this.img.getImgPath());
try {
// Define the path to a local file.
final String filePath = imageFile.getPath();
// Create or overwrite the blob with contents from the local file.
String[] imagePathArray = filePath.split("/");
String imageName = imagePathArray[imagePathArray.length-1];
System.out.println("Image Name: " + imageName);
String containerName = userName + "/" + imageName;
System.out.println("Container Name: " + containerName);
CloudBlockBlob blob= this.getContainer().getBlockBlobReference(containerName);
//UPLOAD!
blob.upload(new FileInputStream(imageFile), imageFile.length());
//-----DATABASE-----//
//create client
this.setDBClient(
new MobileServiceClient(
"URL",
this.act.getApplicationContext()
)
);
this.setImageTable(this.getDBClient().getTable(Image.class));
this.setIcavTable(this.getDBClient().getTable(ICAV.class));
//IMG TABLE QUERY
String validImageID = containerName.replace("/", "_");
Log.d("Azure", "Valid Image ID: " + validImageID);
Image img = new Image(validImageID, this.img.getUser(), this.img.getLat(), this.img.getLon());
this.getImageTable().insert(img);
for(String context : this.img.getContextAttributeMap().keySet()){
Map<String,String> attributeValueMap = this.img.getContextAttributeMap().get(context);
for(String attribute : attributeValueMap.keySet()){
String value = attributeValueMap.get(attribute);
ICAV icavRow = new ICAV();
icavRow.setImageID(validImageID);
icavRow.setContextID(context);
icavRow.setAttributeID(attribute);
icavRow.setValue(value);
this.getIcavTable().insert(icavRow);
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
return null;
}
@Override
protected void onProgressUpdate(Object... object) {
super.onProgressUpdate(object);
Log.d("progressUpdate", "progress: "+((Integer)object[0] * 2) + "%");
}
@Override
protected void onPostExecute(Object o) {
// to do
}
最佳答案
如您所见,Azure SDK 不直接允许这样做,但将您的输入流包装在另一个输入流中应该相当容易,该输入流可以为读取的字节提供回调。类似的东西:
public class ListenableInputStream extends InputStream {
private final InputStream wraped;
private final ReadListener listener;
private final long minimumBytesPerCall;
private long bytesRead;
public ListenableInputStream(InputStream wraped, ReadListener listener, int minimumBytesPerCall) {
this.wraped = wraped;
this.listener = listener;
this.minimumBytesPerCall = minimumBytesPerCall;
}
@Override
public int read() throws IOException {
int read = wraped.read();
if (read >= 0) {
bytesRead++;
}
if (bytesRead > minimumBytesPerCall || read == -1) {
listener.onRead(bytesRead);
bytesRead = 0;
}
return read;
}
@Override
public int available() throws IOException {
return wraped.available();
}
@Override
public void close() throws IOException {
wraped.close();
}
@Override
public synchronized void mark(int readlimit) {
wraped.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
wraped.reset();
}
@Override
public boolean markSupported() {
return wraped.markSupported();
}
interface ReadListener {
void onRead(long bytes);
}
}
minimumBytesPerCall
应该用一些合理的数字初始化,因为您可能不希望在每个字节上都被调用,也许每半兆字节应该是好的。
请记住,这一切都是在 doInBackground
线程上调用的,因此请相应地采取行动。
编辑:
我已经编辑了上面的类,在计算 bytesRead
值时出现了一个小错误。官方文档解释你的后续问题https://developer.android.com/reference/java/io/InputStream.html#read()
Reads the next byte of data from the input stream
因此 read()
如果到达末尾则读取 1 个字节的数据(或返回 -1)。所以是的,必须多次调用它才能读取整个图像。
然后方法 onRead(long)
get 在每次至少 minimumBytesPerCall
被读取时调用(这是为了避免回调每个字节)并再次调用流的结尾(当它返回 -1 时)
传递给 onRead(long)
的值是自上次调用以来已读取的数量。因此,在您的 AsyncTask 上实现它,您必须累加此值并与文件的总大小进行比较。
你的 asynctask 中类似下面的代码应该可以正常工作(假设 Progress
通用参数是一个 Long):
private long fileLength;
private long totalBytes;
private final ListenableInputStream.ReadListener readListener = new ListenableInputStream.ReadListener() {
@Override
public void onRead(long bytes) {
totalBytes += bytes;
publishProgress(totalBytes);
}
};
并在您的上传部分中替换为:
FileInputStream fis = new FileInputStream(imageFile);
fileLength = imageFile.length();
ListenableInputStream lis = new ListenableInputStream(fi, readListener, 256 * 1024); // this will call onRead(long) every 256kb
blob.upload(lis, fileLength);
最后一点,请记住 CloudBlockBlob
内部只是将文件缓存在自己的内存中以供以后上传,或者做任何其他您无法控制的奇怪事情。这段代码所做的只是检查是否读取了完整的文件。
编码愉快!
关于java - Android 跟踪 Azure CloudBlockBlob 上传进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43441951/
我正在尝试将多个 CloudBlockBlob 对象连接到 Azure 函数内的单个 CloudBlockBlob 对象中。我尝试将多个对象下载到内存流中,然后将内存流上传到新对象,但该函数在操作完成
我可能在这里做了一些非常明显错误的事情。我正在 Microsoft.WindowsAzure.Storage 中查找 UploadFromStream()、UploadFromFile()。我只能找到
我们有一个文件系统抽象,使我们能够轻松地在本地和云(Azure)存储之间切换。 对于读取和写入文件,我们有以下成员: Stream OpenRead(); Stream OpenWrite(); 我们
如果 blob 已存在,CloudBlockBlob.UploadText 的行为是什么?它会附加到现有的 blob 中吗?或者抛出异常? 最佳答案 如果您对现有 Blob 调用 CloudBlock
我只是想知道,例如,如果我有一个只有 2MB 的文件。它会使用整个 4MB block 还是只使用 2MB? 我上传了一张33MB的图片到stroage,它被分成4MB的 block 吗? 谢谢 最佳
我使用 azure blob 存储来存储 JSON 文件,并在我的代码中使用 C# API 下载它。 当我下载文本文件的内容并尝试使用 JsonConvert 对其进行反序列化时,出现错误(Visua
我正在尝试对 Azure CloudBlockBlob 进行 Moq 并让它返回一个 Stream 以便我可以测试我的 BlobStorage 存储库是否正在处理正确输出。 但不知何故返回的流总是空的
我正在尝试根据存储帐户中公共(public) blob 的元数据创建 VideoBlob 对象(标题、描述、路径)列表。问题是,当我尝试让变量等于 blob 的元数据(“标题”位于 blob 的元数据
我正在为我拥有的 Web API Web 角色实现 Azure 角色内缓存。我希望能够缓存不经常更改的特定 blob 的 BlobReference。这是我用来获取 BlobReference 的代码
有多种方法可以复制 Azure Blob 存储 block 。 StartCopy 有同步和异步版本。还有一个 BeginStartCopy,它也具有完成回调。 BeginStartCopy 方法明确
我正在使用 CloudBlockBlob 对象和 UploadFromFileAsync 方法将文件上传到 Blob 存储。完成后,我将想要调用一项服务,然后该服务告诉多台计算机获取我上传的文件。但是
我正在使用 CloudBlockBlob 对象和 UploadFromFileAsync 方法将文件上传到 Blob 存储。完成后,我将想要调用一项服务,然后该服务告诉多台计算机获取我上传的文件。但是
我有以下代码: public static void UploadStreamToBlob(Stream stream, string containerName, string blobName)
如果您要转移 Stream通过官方 CloudBlockBlob 到 Azure Blob Storage类,如何监控上传/下载本身的进度?我期待该类会发生一些事件,因为它是一个网络 IO 类,但似乎
我一定在这里遗漏了一些明显的东西,但我发现自己无法进行我认为合法的向上转换。我正在尝试将数据上传到 Azure 中的 Blob 存储,并且想使用方法 CloudBlob.UploadText(stri
我目前使用以下方式上传 CloudBlockBlob: CloudBlockBlob.UploadFromStreamAsync 然后我立即在上面设置了一堆用户元数据。 问题是:我有一个事件网格事件,
我希望这个问题的答案很简单,但在查看 Azure Java API 文档后我无法让它工作。 我正在尝试创建一个空的 CloudBlockBlob,稍后会将 block 上传到其中。我之前已经成功上传了
尝试使用 ASP.NET azure SDK 从 Blob 存储下载图像。 我在另一篇文章中读到,DownloadToStream 确实将 blob 分解成更小的 block 并并行下载它们以提高性能
我正在将文件从 Azure 文件共享复制到存储容器中的 CloudBlockBlob。我想在删除原始文件之前验证两个位置的字节(.Properties.Length)是否相同。我认为这将是获得对复制的
下面的代码示例偶尔会导致访问冲突(5,000 到 10,000 条消息中的 1 条)。使用串行 foreach 而不是 Parallel.ForEach 似乎可以规避该问题。 public void
我是一名优秀的程序员,十分优秀!