我正在尝试修改cloudinary的开源库,以便可以收听照片上传的进度。该库类包含一个MultipartUtility Java类,我对该类进行了修改以侦听上传进度。
修改前的原始代码可以在github上找到:https : //github.com/cloudinary/cloudinary_java/blob/master/cloudinary- android/src/main/java/com/cloudinary/android/MultipartUtility.java
我从字面上进行了修改,使其类似于来自另一个支持上传文件/图像等进度的云服务CloudFS的代码:
https://github.com/bitcasa/CloudFS- Android/blob/master/app/src/main/java/com/bitcasa/cloudfs/api/MultipartUpload.java
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上:如何在android中实现文件上传进度栏:httpConn.setFixedLengthStreamingMode(filesize);
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直接上传到他们的服务器。
cloudname
编辑:
这是我尝试过的方法,当上传实际上在7秒内完成时,它仍在0.7秒内从0-100%跳了起来:
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(); }
使用flush()方法和调用update callback()的时间存在问题。
从代码中可以看到,每次读取图片的一部分时,都将其写入输出缓冲区,但这并不意味着它已发送至服务器,可能已被缓冲,然后稍后写入服务器。 。
您有两个选择,或者在每个outputStream.write()之后调用outputStream.flush(),但这会破坏上载的性能,因为您将失去缓冲的好处。
或者,您可以在方法末尾的outputStream.flush()之后调用updateCallback()。因为在outputStream.flush()之后,您可以确定数据在服务器上,并且进度已经结束。