Android NDK:使用 NDK 上传文件
Posted
技术标签:
【中文标题】Android NDK:使用 NDK 上传文件【英文标题】:Android NDK: File Upload using NDK 【发布时间】:2012-08-28 10:58:07 【问题描述】:有没有使用 NDK 将文件从 SD 上传到服务器的源代码?或任何其他方法上传大文件而不获取
Out Of Memory Exception
如果可以,请给我链接?
下面的代码是我使用的代码,但我得到了内存不足异常
private void UploadFileByClient(LocalFileVO localFileVO)
try
File uploadFile = new File(
(localFileVO.getFolderPath() + "/" + localFileVO.getFileName()));
HttpClient client = new DefaultHttpClient();
final HttpResponse resp;
final HttpClient httpClient = new DefaultHttpClient();
final HttpPut post = new HttpPut("https://qa2-talos-vip-mexico.symnds.com/fileservice/files/");
post.setHeader("User-Agent", "Mexico/1.0.0.57/android");
post.setHeader("Content-Type", localFileVO.getMimeType());
post.setHeader("Authorization", TOKEN);
post.setHeader("x-mexico-endpointid", GUID);
post.setHeader("x-mexico-filehash", localFileVO.getFileHash());
post.setHeader("x-mexico-filesize", localFileVO.getSize());
if (!TextUtils.equals("0", localFileVO.getFolderId()))
post.setHeader("x-mexico-folder", localFileVO.getFolderId());
post.setHeader("x-mexico-filename", localFileVO.getEncodedFileName());
post.setHeader("Expect", "100-continue");
post.setHeader("x-mexico-modtime",
String.valueOf(System.currentTimeMillis() / 1000));
// ParcelFileDescriptor fileDescriptor = this.getContentResolver().openFileDescriptor(Uri.parse(uploadFile.getAbsolutePath()), "r");
// InputStream in = this.getContentResolver().openInputStream(Uri.parse(uploadFile.getAbsolutePath()));
InputStream in = new FileInputStream(uploadFile);
CountingInputStreamEntity entity = new CountingInputStreamEntity(in, uploadFile.length());
entity.setUploadListener(this);
post.setEntity(entity);
resp = httpClient.execute(post);
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
System.out.println("=======================Got the response from server============================");
catch(Exception e)
System.out.println("==============Failed using HttpClient================="+e.getMessage());
private int uploadFile( LocalFileVO localFileVO) throws IOException
UploadFileByClient(localFileVO);
if(true)
return 0;
File uploadFile = new File((localFileVO.getFolderPath() + "/" + localFileVO.getFileName()));
System.setProperty("http.keepAlive", "false");
int code = 0;
try
HttpURLConnection urlConnection;
URL url = new URL("https://qa2-talos-vip-mexico.symnds.com/fileservice/files/");
// URL url = new URL("https://zpi.nortonzone.com/fileservice/files/");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(30000);
urlConnection.setRequestProperty("Host", url.getHost());
// urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setUseCaches(false);
urlConnection.setInstanceFollowRedirects(false);
// urlConnection.setChunkedStreamingMode(1024);
urlConnection.setFixedLengthStreamingMode(Integer.parseInt(localFileVO.getSize()));
//urlConnection.setChunkedStreamingMode(1024);
urlConnection.setRequestMethod("PUT");
urlConnection.setRequestProperty("User-Agent", "Mexico/1.0.0.57/android");
urlConnection.setRequestProperty("Content-Type", localFileVO.getMimeType());
//urlConnection.setRequestProperty("Content-Length", localFileVO.getSize());
urlConnection.setRequestProperty("Authorization", TOKEN);
urlConnection.setRequestProperty("x-mexico-endpointid", GUID);
urlConnection.setRequestProperty("x-mexico-filehash", localFileVO.getFileHash());
//urlConnection.setRequestProperty("x-mexico-filesize", localFileVO.getSize());
if (!TextUtils.equals("0", localFileVO.getFolderId()))
urlConnection.setRequestProperty("x-mexico-folder", localFileVO.getFolderId());
urlConnection.setRequestProperty("x-mexico-filename", localFileVO.getEncodedFileName());
urlConnection.setRequestProperty("Expect", "100-continue");
urlConnection.setRequestProperty("x-mexico-modtime",
String.valueOf(System.currentTimeMillis() / 1000));
bufferOutputStream = new BufferedOutputStream(urlConnection.getOutputStream(),BSIZE);
// CountingOutputStream cOutStream = new CountingOutputStream(bufferOutputStream);
FileInputStream fileInputStream = new FileInputStream(uploadFile);
long startTime = System.currentTimeMillis();
try
int totalSize = 0;
while (true)
synchronized (chunks)
int amountRead = fileInputStream.read(chunks);
System.out.println("========amount read========="+amountRead);
if (amountRead == -1)
break;
bufferOutputStream.write(chunks, 0, amountRead);
bufferOutputStream.flush();
System.out.println("================================TotalSize " + totalSize);
bufferOutputStream.flush();
bufferOutputStream.close();
fileInputStream.close();
catch(Exception e)
e.printStackTrace();
long endTime = System.currentTimeMillis();
System.out.println("=============================================Writing time ==========================================================" + (endTime - startTime));
//code = urlConnection.getResponseCode();
InputStream inputStream = urlConnection.getInputStream();
long endTime1 = System.currentTimeMillis();
System.out.println("Time to get the response is " + (endTime1 - endTime));
// progressBar.setProgress(100);
System.out.println("=================Response code is ================="+code);
urlConnection.disconnect();
//fileInputStream.close();
catch(Exception e)
System.out.println("========================Exception occured=================="+e.getMessage());
return code;
谢谢你
【问题讨论】:
还有,到目前为止你尝试了什么? 我尝试使用 SDK 即 Fileinputstream 和 bufferedoutputstream 进行读写。仅使用这个我得到了 OUT OF MEMORY EXCEPTION(尝试上传 20MB zip 文件) 好,你应该上传那个代码,这样我们才能更好地帮助你亲爱的:) 我用代码编辑了我的问题 好的,如果有的话,也上传错误日志。 【参考方案1】:您不需要 NDK。如果没有您的代码,我只能建议有将整个文件读入缓冲区的代码。这是错误的。执行以下操作: 分小部分读取文件并将这些部分一一发送到输出流(从连接中获取)
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);
// 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() );
....
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
serverResponseCode = connection.getResponseCode();
serverResponseMessage = connection.getResponseMessage();
fileInputStream.close();
outputStream.flush();
outputStream.close();
【讨论】:
先生,我有一个疑问.. 此代码不会显示任何 Out Of Memory Exception ? bcoz iam 试图上传一个非常大的文件,大小约为 Min 20 MB - Max 150 MB 我在这里没有工作示例,但是基于这种方法的应用程序可以很好地上传视频文件。如果我没记错的话,它是前一段时间用谷歌搜索的,我在这里重新找到了这个样本coderzheaven.com/2012/03/29/… sir 代码对于 5MB 文件很好,但是当我使用 20MB 文件时,应用程序崩溃了.. 帮助我【参考方案2】:您似乎错过了 setChunkedStreamingMode(int) 调用 来自:http://developer.android.com/reference/java/net/HttpURLConnection.html 发布内容 要将数据上传到 Web 服务器,请使用 setDoOutput(true) 配置输出连接。 为了获得最佳性能,您应该在预先知道主体长度时调用 setFixedLengthStreamingMode(int),或者在不知道时调用 setChunkedStreamingMode(int)。否则 HttpURLConnection 将被强制在内存中缓冲完整的请求正文,然后再传输,浪费(并且可能耗尽)堆并增加延迟。
但是您的内容太大而无法缓冲。
【讨论】:
先生,我无法理解 body length 一词(当预先知道 body 长度时)..您是否指定了文件的大小 先生,我试过 setChunkedStreamingMode(1000*1024) 但还是同样的错误。以上是关于Android NDK:使用 NDK 上传文件的主要内容,如果未能解决你的问题,请参考以下文章