通过http上传时Android图像损坏
当我将图像从 Android 设备(v 2.2)上传到服务器(带有 php 的 apache)时 基本上,有与这里相同的问题: Android Development Image Upload Corrupted
首先,上传方法基于 apache httpcomponent 4.1,我认为问题出在其中。然后我基于HttpURLConnection编写了自己的上传库。
我尝试使用不同的服务器,但仍然是一样的。
示例:
http://pixelbirthcloud.com/corrupted_images/1_orig.jpg - 原始图像
http://pixelbirthcloud.com/corrupted_images/1_corrupted.jpg - 我们在服务器上得到的内容。
文件大小相同,但内容中的内容有一个损坏的字节块:
00051330 | 49 69 11 4B 9D E6 | 00051330 | DA BB 10 70 DC 77 |
00051338 | 2D B9 1B B9 E4 81 5A E6 | 00051338 | AC 20 C7 90 7E B4 33 80 |
00051340 | D4 14 B0 F4 EA 3D D1 E9 | 00051340 | 31 9A B8 C2 29 83 66 9C |
00051348 | 61 9D E3 38 F7 36 DE 63 | 00051348 | 9A 84 8E 73 9A 8D B5 29 |
00051350 | 25 9D 9D C4 64 C3 23 AA | 00051350 | 18 60 1C 0F 7A CF 33 01 |
00051358 | 4A EB 08 C3 97 7C 8C 36 | 00051358 | D4 F0 7A D3 24 BA 85 71 |
00051360 | 73 F5 E3 15 14 5B BC C1 | 00051360 | F3 0A 76 8A D6 C4 36 5E |
00051368 | B9 A4 49 06 71 1B 11 87 | 00051368 | 7B B9 5F 20 E3 A5 46 F2 |
00051370 | 39 E7 76 7B 8F 5F | 00051370 | B8 1D 4E 6B 36 6D |
我不知道它取决于什么,但在我客户的设备上,图像损坏得更多。有时上传正常,但大多数时候上传的图像已损坏。
所以我猜这与http传输无关。它是关于将流从 SD 卡获取到内存,然后将该流保存到 http...
代码如下。
你们有什么想法吗?尝试了一切,但仍然不起作用。
public String execute() throws IOException {
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****MultipartBoundary";
try {
URL url = new URL(mUri);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
// timeouts
conn.setConnectTimeout(CONNECT_TIMEOUT);
conn.setReadTimeout(READ_TIMEOUT);
Log.d(TAG, "Opening connectionStream");
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
Log.d(TAG, "Adding params");
for (NameValuePair param : mParams) {
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: post-data; name="
+ param.getName() + lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(param.getValue());
dos.writeBytes(lineEnd);
}
File file;
Log.d(TAG, "Adding files");
for (NameValuePair param : mFiles) {
file = new File(param.getValue());
if (file.exists()) {
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: post-data; name="
+ param.getName() + "; filename=" + file.getName()
+ lineEnd);
dos.writeBytes("Content-Type: application/octet-stream" + lineEnd);
dos.writeBytes("Content-Transfer-Encoding: binary" + lineEnd);
dos.writeBytes(lineEnd);
Log.d(TAG, "Opening fileInputStream");
FileInputStream fileStream = new FileInputStream(file);
try {
int bytesAvailable;
while((bytesAvailable = fileStream.available()) > 0)
{
int bufferSize = Math.min(bytesAvailable, 4096);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileStream.read(buffer, 0, bufferSize);
dos.write(buffer, 0, bytesRead);
}
dos.writeBytes(lineEnd);
} finally {
fileStream.close();
}
Log.d(TAG, "Closing fileINputStream");
}
}
// very important - we specify the end of the multipart block
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
dos.flush();
dos.close();
// getting response
if (conn.getResponseCode() == HttpStatus.SC_OK) {
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
try {
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int read = 0;
int bufSize = 512;
byte[] buffer = new byte[bufSize];
while(true){
read = bis.read(buffer);
if(read==-1){
break;
}
baf.append(buffer, 0, read);
}
Log.d(TAG, "Connection successful - returning result");
return new String(baf.toByteArray(), "UTF-8");
} finally {
bis.close();
}
} else {
Log.d(TAG, "Return code is " + Integer.toString(conn.getResponseCode()));
throw new IOException("Return code is " + Integer.toString(conn.getResponseCode()));
}
} catch (MalformedURLException e) {
Log.e(TAG, "Exception: " + e.getMessage(), e);
throw new IOException("aaa");
} catch (IOException e) {
Log.e(TAG, "Exception: " + e.getMessage(), e);
throw new IOException();
}
}
更新:
考虑到创建流时的数据损坏......所以我稍微更改了代码以从源流保存文件:
FileOutputStream fileOutStream = new FileOutputStream(AndorraApplication.getPhotosPath() + "/orig_" +file.getName() );
DataOutputStream dataOutStream = new DataOutputStream(fileOutStream);
try {
int bytesAvailable;
while((bytesAvailable = fileStream.available()) > 0)
{
int bufferSize = Math.min(bytesAvailable, 4096);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileStream.read(buffer, 0, bufferSize);
dos.write(buffer, 0, bytesRead);
dataOutStream.write(buffer, 0, bytesRead);
}
dos.writeBytes(lineEnd);
} finally {
fileStream.close();
dataOutStream.close();
}
结果是,虽然上传的图像已损坏,但使用 dataOutStream 存储的图像是好的......现在完全丢失了。
Froyo 上的 HTTPUrlConnection 是否有错误?
When I upload image from android device (v 2.2) to a server (apache with php)
basically, have same problem as here: Android Development Image Upload Corrupted
At first, the upload method was based on apache httpcomponent 4.1 and i thought the problem was in it. Then I have written my own upload library based on HttpURLConnection.
I tried to use different servers, but it is still the same.
Example:
http://pixelbirthcloud.com/corrupted_images/1_orig.jpg - the original image
http://pixelbirthcloud.com/corrupted_images/1_corrupted.jpg - what we get on server.
File size is the same, but the content in the content there is a corrupted block of bytes:
00051330 | 49 69 11 4B 9D E6 | 00051330 | DA BB 10 70 DC 77 |
00051338 | 2D B9 1B B9 E4 81 5A E6 | 00051338 | AC 20 C7 90 7E B4 33 80 |
00051340 | D4 14 B0 F4 EA 3D D1 E9 | 00051340 | 31 9A B8 C2 29 83 66 9C |
00051348 | 61 9D E3 38 F7 36 DE 63 | 00051348 | 9A 84 8E 73 9A 8D B5 29 |
00051350 | 25 9D 9D C4 64 C3 23 AA | 00051350 | 18 60 1C 0F 7A CF 33 01 |
00051358 | 4A EB 08 C3 97 7C 8C 36 | 00051358 | D4 F0 7A D3 24 BA 85 71 |
00051360 | 73 F5 E3 15 14 5B BC C1 | 00051360 | F3 0A 76 8A D6 C4 36 5E |
00051368 | B9 A4 49 06 71 1B 11 87 | 00051368 | 7B B9 5F 20 E3 A5 46 F2 |
00051370 | 39 E7 76 7B 8F 5F | 00051370 | B8 1D 4E 6B 36 6D |
I don't know what it depends on, but on my clients' devices the images get much more corrupted. Sometimes it uploads fine, but most of the time the uploaded images are corrupted.
So I guess it's not about the http transfer. it is something about getting stream from sd card to memory and then saving that stream to http...
The code is below.
Do you guys have any ideas? Tried everything and still it doesn't' work.
public String execute() throws IOException {
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****MultipartBoundary";
try {
URL url = new URL(mUri);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
// timeouts
conn.setConnectTimeout(CONNECT_TIMEOUT);
conn.setReadTimeout(READ_TIMEOUT);
Log.d(TAG, "Opening connectionStream");
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
Log.d(TAG, "Adding params");
for (NameValuePair param : mParams) {
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: post-data; name="
+ param.getName() + lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(param.getValue());
dos.writeBytes(lineEnd);
}
File file;
Log.d(TAG, "Adding files");
for (NameValuePair param : mFiles) {
file = new File(param.getValue());
if (file.exists()) {
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: post-data; name="
+ param.getName() + "; filename=" + file.getName()
+ lineEnd);
dos.writeBytes("Content-Type: application/octet-stream" + lineEnd);
dos.writeBytes("Content-Transfer-Encoding: binary" + lineEnd);
dos.writeBytes(lineEnd);
Log.d(TAG, "Opening fileInputStream");
FileInputStream fileStream = new FileInputStream(file);
try {
int bytesAvailable;
while((bytesAvailable = fileStream.available()) > 0)
{
int bufferSize = Math.min(bytesAvailable, 4096);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileStream.read(buffer, 0, bufferSize);
dos.write(buffer, 0, bytesRead);
}
dos.writeBytes(lineEnd);
} finally {
fileStream.close();
}
Log.d(TAG, "Closing fileINputStream");
}
}
// very important - we specify the end of the multipart block
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
dos.flush();
dos.close();
// getting response
if (conn.getResponseCode() == HttpStatus.SC_OK) {
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
try {
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int read = 0;
int bufSize = 512;
byte[] buffer = new byte[bufSize];
while(true){
read = bis.read(buffer);
if(read==-1){
break;
}
baf.append(buffer, 0, read);
}
Log.d(TAG, "Connection successful - returning result");
return new String(baf.toByteArray(), "UTF-8");
} finally {
bis.close();
}
} else {
Log.d(TAG, "Return code is " + Integer.toString(conn.getResponseCode()));
throw new IOException("Return code is " + Integer.toString(conn.getResponseCode()));
}
} catch (MalformedURLException e) {
Log.e(TAG, "Exception: " + e.getMessage(), e);
throw new IOException("aaa");
} catch (IOException e) {
Log.e(TAG, "Exception: " + e.getMessage(), e);
throw new IOException();
}
}
UPDATES:
thought about data corruption when creating streams.. so i changed a code a bit to save the file from the source stream:
FileOutputStream fileOutStream = new FileOutputStream(AndorraApplication.getPhotosPath() + "/orig_" +file.getName() );
DataOutputStream dataOutStream = new DataOutputStream(fileOutStream);
try {
int bytesAvailable;
while((bytesAvailable = fileStream.available()) > 0)
{
int bufferSize = Math.min(bytesAvailable, 4096);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileStream.read(buffer, 0, bufferSize);
dos.write(buffer, 0, bytesRead);
dataOutStream.write(buffer, 0, bytesRead);
}
dos.writeBytes(lineEnd);
} finally {
fileStream.close();
dataOutStream.close();
}
And it comes that while the uploaded image is corrupted, the image stored using dataOutStream is good... completely lost now.
is there a bug in HTTPUrlConnection on Froyo or something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
检查我在这里回答如何将文件(让它成为内存中的图像文件或任何文件)上传到服务器。
Android httpclient文件上传数据损坏和超时问题
它对我上传图像非常有用。
check i answer here how to upload a file(let it be a image file from memory or any file) to a server..
Android httpclient file upload data corruption and timeout issues
it worked great for me for uploading image.