我正在尝试修改cloudinary的开源库,以便我可以听取上传照片的进度。库类包含一个MultipartUtility java类,我修改该类来监听上传的进度。 https://github.com/cloudinary/cloudinary_java/blob/master/cloudinary-android/src/main/java/com/cloudinary/android/MultipartUtility.javaAndroid:在Cloudinary中用HttpURLConnection中的进度回调上传照片
我硬是修改它类似于从另一个云服务CloudFS上传文件/图片等时,支持进度代码:
修改之前,原代码可以在GitHub上找到
package com.cloudinary.android;
import com.cloudinary.Cloudinary;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
/**
* This utility class provides an abstraction layer for sending multipart HTTP
* POST requests to a web server.
*
* @author www.codejava.net
* @author Cloudinary
*/
public class MultipartUtility {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
private HttpURLConnection httpConn;
private String charset;
private OutputStream outputStream;
private PrintWriter writer;
UploadingCallback uploadingCallback;
public final static String USER_AGENT = "CloudinaryAndroid/" + Cloudinary.VERSION;
Long filesize;
public void setUploadingCallback(UploadingCallback uploadingCallback) {
this.uploadingCallback = uploadingCallback;
}
/**
* This constructor initializes a new HTTP POST request with content type is
* set to multipart/form-data
*
* @param requestURL
* @param charset
* @throws IOException
*/
public MultipartUtility(String requestURL, String charset, String boundary, Map<String, String> headers, Long filesize) throws IOException {
this.charset = charset;
this.boundary = boundary;
this.filesize = filesize;
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setFixedLengthStreamingMode(filesize); //added this in
if (headers != null) {
for (Map.Entry<String, String> header : headers.entrySet()) {
httpConn.setRequestProperty(header.getKey(), header.getValue());
}
}
httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
httpConn.setRequestProperty("User-Agent", USER_AGENT);
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true);
}
public MultipartUtility(String requestURL, String charset, String boundary) throws IOException {
this(requestURL, charset, boundary, null, 0L);
}
/**
* Adds a form field to the request
*
* @param name field name
* @param value field value
*/
public void addFormField(String name, String value) {
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + name + "\"").append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=" + charset).append(LINE_FEED);
writer.append(LINE_FEED);
writer.append(value).append(LINE_FEED);
writer.flush();
}
/**
* Adds a upload file section to the request
*
* @param fieldName name attribute in {@code <input type="file" name="..." />}
* @param uploadFile a File to be uploaded
* @throws IOException
*/
public void addFilePart(String fieldName, File uploadFile, String fileName) throws IOException {
if (fileName == null) fileName = uploadFile.getName();
FileInputStream inputStream = new FileInputStream(uploadFile);
addFilePart(fieldName, inputStream, fileName);
}
public void addFilePart(String fieldName, File uploadFile) throws IOException {
addFilePart(fieldName, uploadFile, "file");
}
public void addFilePart(String fieldName, InputStream inputStream, String fileName) throws IOException {
if (fileName == null) fileName = "file";
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"" + fileName + "\"").append(LINE_FEED);
writer.append("Content-Type: ").append(APPLICATION_OCTET_STREAM).append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
int progress = 0;
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
progress += bytesRead;
/* int percentage = ((progress/filesize.intValue()) * 100);*/
if (uploadingCallback != null) {
uploadingCallback.uploadListener(progress);
}
}
outputStream.flush();
writer.flush();
uploadingCallback = null;
inputStream.close();
writer.append(LINE_FEED);
writer.flush();
}
public void addFilePart(String fieldName, InputStream inputStream) throws IOException {
addFilePart(fieldName, inputStream, "file");
}
/**
* Completes the request and receives response from the server.
*
* @return a list of Strings as response in case the server returned status
* OK, otherwise an exception is thrown.
* @throws IOException
*/
public HttpURLConnection execute() throws IOException {
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.close();
return httpConn;
}
}
我所做的更改是在本主题推荐的httpURLConnection上添加以下内容:How to implement file upload progress bar in android:httpConn.setFixedLengthStreamingMode(filesize);
然后,我创建了一个简单的界面来监听上传进度:
public interface UploadingCallback {
void uploadListener(int progress);
}
然后我重视它,而HttpURLConnection类写道照片:
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
progress += bytesRead;
/* int percentage = ((progress/filesize.intValue()) * 100);*/
if (uploadingCallback != null) {
uploadingCallback.uploadListener(progress);
}
}
的代码运行,但进度的上传似乎没有被正确测量。这张照片大约365kb,上传时间大约为十分之一秒(我开始在17:56:55.481上传,17:56:55.554上传完成,那只是0.7秒)。我不相信我的互联网连接速度很快,并期望它至少需要5秒钟。我有一种感觉,那就是测量将照片写入缓冲区所用的时间,而不是将其发送到cloudinary服务器所用的时间。
我怎样才能测量上传照片所需的时间,以便我可以将数据用于我的进度条?
04-24 17:56:55.481 28306-28725/com.a upload 4096
04-24 17:56:55.486 28306-28725/com.a upload 8192
04-24 17:56:55.486 28306-28725/com.a upload 12288
04-24 17:56:55.486 28306-28725/com.a upload 16384
04-24 17:56:55.487 28306-28725/com.a upload 20480
04-24 17:56:55.487 28306-28725/com.a upload 24576
04-24 17:56:55.487 28306-28725/com.a upload 28672
04-24 17:56:55.487 28306-28725/com.a upload 32768
04-24 17:56:55.491 28306-28725/com.a upload 36864
04-24 17:56:55.492 28306-28725/com.a upload 40960
04-24 17:56:55.493 28306-28725/com.a upload 45056
04-24 17:56:55.493 28306-28725/com.a upload 49152
04-24 17:56:55.493 28306-28725/com.a upload 53248
04-24 17:56:55.493 28306-28725/com.a upload 57344
04-24 17:56:55.494 28306-28725/com.a upload 61440
04-24 17:56:55.494 28306-28725/com.a upload 65536
04-24 17:56:55.494 28306-28725/com.a upload 69632
04-24 17:56:55.494 28306-28725/com.a upload 73728
04-24 17:56:55.494 28306-28725/com.a upload 77824
04-24 17:56:55.495 28306-28725/com.a upload 81920
04-24 17:56:55.495 28306-28725/com.a upload 86016
04-24 17:56:55.495 28306-28725/com.a upload 90112
04-24 17:56:55.495 28306-28725/com.a upload 94208
04-24 17:56:55.495 28306-28725/com.a upload 98304
04-24 17:56:55.495 28306-28725/com.a upload 102400
04-24 17:56:55.495 28306-28725/com.a upload 106496
04-24 17:56:55.496 28306-28725/com.a upload 110592
04-24 17:56:55.496 28306-28725/com.a upload 114688
04-24 17:56:55.496 28306-28725/com.a upload 118784
04-24 17:56:55.497 28306-28725/com.a upload 122880
04-24 17:56:55.498 28306-28725/com.a upload 126976
04-24 17:56:55.498 28306-28725/com.a upload 131072
04-24 17:56:55.498 28306-28725/com.a upload 135168
04-24 17:56:55.498 28306-28725/com.a upload 139264
04-24 17:56:55.499 28306-28725/com.a upload 143360
04-24 17:56:55.506 28306-28725/com.a upload 147456
04-24 17:56:55.510 28306-28725/com.a upload 151552
04-24 17:56:55.510 28306-28725/com.a upload 155648
04-24 17:56:55.514 28306-28725/com.a upload 159744
04-24 17:56:55.515 28306-28725/com.a upload 163840
04-24 17:56:55.517 28306-28725/com.a upload 167936
04-24 17:56:55.517 28306-28725/com.a upload 172032
04-24 17:56:55.518 28306-28725/com.a upload 176128
04-24 17:56:55.518 28306-28725/com.a upload 180224
04-24 17:56:55.518 28306-28725/com.a upload 184320
04-24 17:56:55.519 28306-28725/com.a upload 188416
04-24 17:56:55.519 28306-28725/com.a upload 192512
04-24 17:56:55.519 28306-28725/com.a upload 196608
04-24 17:56:55.519 28306-28725/com.a upload 200704
04-24 17:56:55.520 28306-28725/com.a upload 204800
04-24 17:56:55.525 28306-28725/com.a upload 208896
04-24 17:56:55.526 28306-28725/com.a upload 212992
04-24 17:56:55.527 28306-28725/com.a upload 217088
04-24 17:56:55.530 28306-28725/com.a upload 221184
04-24 17:56:55.530 28306-28725/com.a upload 225280
04-24 17:56:55.530 28306-28725/com.a upload 229376
04-24 17:56:55.530 28306-28725/com.a upload 233472
04-24 17:56:55.530 28306-28725/com.a upload 237568
04-24 17:56:55.531 28306-28725/com.a upload 241664
04-24 17:56:55.532 28306-28725/com.a upload 245760
04-24 17:56:55.532 28306-28725/com.a upload 249856
04-24 17:56:55.532 28306-28725/com.a upload 253952
04-24 17:56:55.533 28306-28725/com.a upload 258048
04-24 17:56:55.533 28306-28725/com.a upload 262144
04-24 17:56:55.535 28306-28725/com.a upload 266240
04-24 17:56:55.540 28306-28725/com.a upload 270336
04-24 17:56:55.540 28306-28725/com.a upload 274432
04-24 17:56:55.541 28306-28725/com.a upload 278528
04-24 17:56:55.541 28306-28725/com.a upload 282624
04-24 17:56:55.543 28306-28725/com.a upload 286720
04-24 17:56:55.545 28306-28725/com.a upload 290816
04-24 17:56:55.545 28306-28725/com.a upload 294912
04-24 17:56:55.547 28306-28725/com.a upload 299008
04-24 17:56:55.547 28306-28725/com.a upload 303104
04-24 17:56:55.547 28306-28725/com.a upload 307200
04-24 17:56:55.547 28306-28725/com.a upload 311296
04-24 17:56:55.547 28306-28725/com.a upload 315392
04-24 17:56:55.548 28306-28725/com.a upload 319488
04-24 17:56:55.548 28306-28725/com.a upload 323584
04-24 17:56:55.548 28306-28725/com.a upload 327680
04-24 17:56:55.548 28306-28725/com.a upload 331776
04-24 17:56:55.549 28306-28725/com.a upload 335872
04-24 17:56:55.549 28306-28725/com.a upload 339968
04-24 17:56:55.549 28306-28725/com.a upload 344064
04-24 17:56:55.550 28306-28725/com.a upload 348160
04-24 17:56:55.550 28306-28725/com.a upload 352256
04-24 17:56:55.551 28306-28725/com.a upload 356352
04-24 17:56:55.551 28306-28725/com.a upload 360448
04-24 17:56:55.552 28306-28725/com.a upload 364544
04-24 17:56:55.554 28306-28725/com.a upload 365790
为了测试这一点为自己,你将需要创建cloudinary网站免费帐户,以获得您的cloudname
这样你就可以在Android SDK直接连接到他们的服务从Android的无符号直接上传到他们的服务器
编辑:
这是我曾尝试,它仍然从0跳到 - 100%0.7秒时上传在7秒内的时间实际上完成:
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
progress += bytesRead;
Log.d("MultiPart", "file transferred so far: "
+ progress);
if (uploadingCallback != null) {
uploadingCallback.uploadListener(progress);
}
Log.d("Flushing", "flush the writer");
outputStream.flush();
writer.flush();
}
你的第二个选择让人很没有意义,因为这也将是在100%,而我试图做的是整个目的得到了一个进度指示器上传。我尝试了你的第一个选择,它似乎并没有工作,我已经放入一个编辑,以显示你想我已经尝试过。 – Simon
比你需要做一些类似于ug__的建议。你应该在一段时间内调用flush():),但正如我从你的改变中看到的那样,即使这对你没有任何作用。我需要测试这个,并让你知道,但我99%确定调用flush()是正确的路要走。也许你的代码的其他部分存在问题。将需要测试这个,我会马上去做。 – aleksamarkoni
技术上,呼吁为OutputStream齐平,该文档称,它什么事也不会做任何事情:https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#flush()我将其转换为DataOutputStream以查看它现在是否会有所作为。它实际上没有区别。 – Simon