在Android中上传大文件而不会出现内存不足错误
Posted
技术标签:
【中文标题】在Android中上传大文件而不会出现内存不足错误【英文标题】:Upload large file in Android without outofmemory error 【发布时间】:2012-03-26 16:33:21 【问题描述】:我的上传代码如下:
String end = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
try
URL url = new URL(ActionUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestMethod("POST");
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Accept", "text/*");
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
DataOutputStream ds = new DataOutputStream(con.getOutputStream());
ds.writeBytes(twoHyphens + boundary + end);
ds.writeBytes("Content-Disposition: form-data;" + "name=\"folder\"" + end + end);
ds.write(SavePath.getBytes("UTF-8"));
ds.writeBytes(end);
ds.writeBytes(twoHyphens + boundary + end);
ds.writeBytes("Content-Disposition: form-data;" + "name=\"Filedata\"; filename=\"");
ds.write(FileName.getBytes("UTF-8"));
ds.writeBytes("\"" + end);
ds.writeBytes(end);
FileInputStream fStream = new FileInputStream(uploadFilepath+""+FileName);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = -1;
int pro = 0;
while((length = fStream.read(buffer)) != -1)
ds.write(buffer, 0, length);
ds.writeBytes(end);
ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
fStream.close();
ds.flush();
InputStream is = con.getInputStream();
int ch;
StringBuffer b = new StringBuffer();
while((ch = is.read()) != -1)
b.append((char)ch);
ds.close();
catch(Exception e)
e.printStackTrace();
虽然小于 16 mb,但它上传成功。 但当它超过 16 mb 时,“OutOfMemory”错误显示。 如何避免内存不足错误?
【问题讨论】:
我想在 while((length = fStream.read(buffer)) != -1) 循环中每次发送 1024 个字节,但我不知道该怎么做。 brian,请参考我的回答:***.com/questions/4455006/… 嘿@brian,你能发布服务器端代码 【参考方案1】:你尝试过使用
con.setChunkedStreamingMode(1024);
这将帮助您将数据分块为特定大小,这样您就无需将整个文件保存在内存中。
更新:
尝试使用以下方法。我使用这种方法上传一个 80 mb 的文件,没有异常。
public String sendFileToServer(String filename, String targetUrl)
String response = "error";
Log.e("Image filename", filename);
Log.e("url", targetUrl);
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
// DataInputStream inputStream = null;
String pathToOurFile = filename;
String urlServer = targetUrl;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
DateFormat df = new SimpleDateFormat("yyyy_MM_dd_HH:mm:ss");
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024;
try
FileInputStream fileInputStream = new FileInputStream(new File(
pathToOurFile));
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setChunkedStreamingMode(1024);
// Enable POST method
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
String connstr = null;
connstr = "Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
+ pathToOurFile + "\"" + lineEnd;
Log.i("Connstr", connstr);
outputStream.writeBytes(connstr);
outputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
Log.e("Image length", bytesAvailable + "");
try
while (bytesRead > 0)
try
outputStream.write(buffer, 0, bufferSize);
catch (OutOfMemoryError e)
e.printStackTrace();
response = "outofmemoryerror";
return response;
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
catch (Exception e)
e.printStackTrace();
response = "error";
return response;
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens
+ lineEnd);
// Responses from the server (code and message)
int serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();
Log.i("Server Response Code ", "" + serverResponseCode);
Log.i("Server Response Message", serverResponseMessage);
if (serverResponseCode == 200)
response = "true";
String CDate = null;
Date serverTime = new Date(connection.getDate());
try
CDate = df.format(serverTime);
catch (Exception e)
e.printStackTrace();
Log.e("Date Exception", e.getMessage() + " Parse Exception");
Log.i("Server Response Time", CDate + "");
filename = CDate
+ filename.substring(filename.lastIndexOf("."),
filename.length());
Log.i("File Name in Server : ", filename);
fileInputStream.close();
outputStream.flush();
outputStream.close();
outputStream = null;
catch (Exception ex)
// Exception handling
response = "error";
Log.e("Send file Exception", ex.getMessage() + "");
ex.printStackTrace();
return response;
【讨论】:
我尝试添加到 con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); 行的下方,但所有文件都上传失败。跨度> 错误 java.io.FileNotFoundException: ip/web/jquery/uploader/uploadify.php 显示。 * 对于在 App Engine 中使用此出色代码的任何人:在构建 connstr 的行中,在 filename= (...name=\"uploadedfile\"; filename=...) 之前添加一个空格/跨度> @AndroSelva:如果我想向多部分实体添加更多部分?我只是在输出流中添加换行符并添加我想要的数据?假设我想添加一个名为“json”的 json 字符串和另一个文件。 我把 setChunkedStreamingMode(1024);在我的代码中,我得到: HTTP/1.1 400 Bad RequestContent-Length: 11Content-Type: text/plainBad Request【参考方案2】:如果服务器接受分块模式,你可以使用
((HttpURLConnection) con).setChunkedStreamingMode(chunkLength)
否则你可以使用
((HttpURLConnection) con).setChunkedStreamingMode(0);
或
/* compute first your request content length
contentLength = formBodyLength + yourFileSize
*/
con.setRequestProperty("Content-Length", String.valueOf(contentLength));
((HttpURLConnection) con).setFixedLengthStreamingMode(contentLength);
终于...发送你想要的东西
【讨论】:
【参考方案3】:bitmap=Bitmap.createScaledBitmap(bitmap, 100, 100, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); //compress to format you want.
byte [] byte_arr = stream.toByteArray();
String image_str = Base64.encodeBytes(byte_arr);
我尝试过的最佳方式对我来说是成功的!!!
【讨论】:
压缩方法链接:developer.android.com/reference/android/graphics/Bitmap.html 问题不是关于图像,而是关于一般文件以上是关于在Android中上传大文件而不会出现内存不足错误的主要内容,如果未能解决你的问题,请参考以下文章