视频文件中的OutOfMemory异常上传到服务器android

时间:2014-12-02 13:15:39

标签: android

在发布这个问题之前,我已经在堆栈溢出中搜索了很多但是找不到解决方案..其中一些是..

How to Upload Large Video FIle on server?

video upload in Android

Upload large file in Android without outofmemory error

Upload files by post to server OutOfMemory

Upload file in Android with outofmemory error     等.....

我正在上传文件管理器/mfs_candidate_intro/65850.mp4内的视频文件

现在的MainActivity.java

package com.servicedemo;

import java.io.File;

import android.support.v7.app.ActionBarActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;


public class MainActivity extends ActionBarActivity {


    private String fpath;
    private String myfile;
    private static final String UPLOAD_URL = "http://www.ourgoalplan.com/CandidateIntroUploader.ashx";
    private int candidateID =65850; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }


   public void startMethod(View v) {

       fpath=setVideoOutPutFile();
       Intent i=new Intent(MainActivity.this,Uploadservice.class);
        i.putExtra("filepath", fpath);
        i.putExtra("uploadurl", UPLOAD_URL);
        i.putExtra("candidateID", candidateID);
        startService(i);
}



   private String setVideoOutPutFile()
    {
        File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "/mfs_candidate_intro");

        if (!mediaStorageDir.exists())
        {
            if (!mediaStorageDir.mkdirs())
            {
                Log.d("VideoLogger", "failed to create directory");
            }
        }

        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
        Log.e("external storagedirectory path= =", path);
        myfile = path + "/mfs_candidate_intro/" + candidateID + ".mp4";
        Log.e("external final file = =", myfile);
        return myfile;
    }



}

Uploadservice.java包含

package com.servicedemo;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.io.FileUtils;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class Uploadservice extends IntentService{

    private String uploadURL;
    private int candidateID;
    private String FilePath;

    public Uploadservice() {      
        super("My service");

    }

    @Override
    public IBinder onBind(Intent intent) {
    return null;
    }



    @Override
    protected void onHandleIntent(Intent intent) {   //After completion of onstartcommand system will deliver all intent object to onHandleItent method.          

        uploadURL=intent.getExtras().getString("uploadurl");
        candidateID=intent.getExtras().getInt("candidateID");
        FilePath =intent.getExtras().getString("filepath");
        Log.d("Inside onhandleIntent", FilePath);
        try {
            uploadVideo(uploadURL,candidateID,FilePath);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }


    public byte[] filecovert(String path)
    {
        return null;

    }

    public void uploadVideo(String iUploadUrl, int iCandidateId, String iFilePath) throws IOException
    {
        /**
         * converts the file in the specified path to byte Array
         */
        byte[] videobytes = convertFileToBytes(iFilePath);


        // Number of chunks in Bytes..
        final long chunkSize = 100000;
        // creates a new file in the specified path..
        File videoFile = new File(iFilePath);



        if (videobytes != null && videobytes.length > 0)
        {


            String requestUri = iUploadUrl + "?CandidateID=" + iCandidateId + "&fileName=" + videoFile.getName();

            // get the number of chunks
            long numOfChunks = (videobytes.length / chunkSize);
            byte[] byteArray = new byte[(int) chunkSize];

            /**
             * Get the remaining Bytes. /Check if there is some bytes remaining after calculation of numOfChunks
             */
            long remaingbytes = videobytes.length % chunkSize;
            if (remaingbytes > 0)
            {
                // Increase number of chunks by one if some bytes are left ...
                numOfChunks = numOfChunks + 1;
            }
            long copyBytesLength = chunkSize;

            for (int chunkNo = 1; chunkNo <= numOfChunks; chunkNo++)
            {
                String requestURL = requestUri + "&TotalChunks=" + numOfChunks + "&ChunkCounter=" + chunkNo;
                copyBytesLength = ((chunkNo * chunkSize) > videobytes.length) ? remaingbytes : chunkSize;
                byteArray = new byte[(int) copyBytesLength];
                System.arraycopy(videobytes, (int) ((chunkNo - 1) * chunkSize), byteArray, 0, (int) copyBytesLength);

                // send request to Handler
                if (requestHandler(numOfChunks, byteArray, chunkNo, requestURL))
                {
                    Log.e("SplashScreen", "Request Handler Returns False " + iCandidateId);
                    break;
                }
            }
        }
    }

    /**
     * This method provides the file data as byte array
     * 
     * @param iFilePath
     *            the path to the file
     * @return the corresponding byte array representation
     * @throws IOException
     */
    private byte[] convertFileToBytes(String iFilePath) throws IOException
    {
        return FileUtils.readFileToByteArray(new File(iFilePath));
    }

    /**
     * This method handles the division of byte array data into small chunks
     * 
     * @param iNumOfChunks
     *            number of chunks available after dividing data as separate 1 MB units
     * @param iByteArray
     *            the byte array representation of video data.
     * @param iChunkNum
     *            current chunk number
     * @param iRequestURL
     *            complete upload url
     * @return true/false based upon the success result.
     */
    private boolean requestHandler(long iNumOfChunks, byte[] iByteArray, int iChunkNum, String iRequestURL)
    {
        try
        {
            boolean valid = true;
            HttpURLConnection conn = null;
            DataOutputStream dos = null;
            DataInputStream inStream = null;
            URL url = new URL(iRequestURL);
            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", "application/x-www-form-urlencoded");
            dos = new DataOutputStream(conn.getOutputStream());
            // Writes iByteArray.length from IByteArray starting at offset 0 to the dos output stream.
            dos.write(iByteArray, 0, iByteArray.length);
            dos.flush();
            dos.close();
            // get the response code returned by the HTTP server...
            int responseCode = conn.getResponseCode();
            Log.e("SplashScreen", "Response code is " + responseCode);
            /**
             * If response code is OK ,Check if the iChunkNum == iNumOfChunks If it is equal ,it means Writting to th
             */
            if (responseCode == HttpURLConnection.HTTP_OK)
            {
                if (iChunkNum == iNumOfChunks)
                {
                    inStream = new DataInputStream(conn.getInputStream());
                    String str;
                    StringBuffer buf = new StringBuffer();
                    while ((str = inStream.readLine()) != null)
                    {
                        buf.append(str);
                    }
                    str = buf.toString();
                    Log.e("SplashScreen", "Server Response" + str);
                    inStream.close();
                }
                else
                {
                    valid = false;
                }
            }
            return valid;
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return false;
        }

    }

 @Override
public void onDestroy() {
    Log.d("destroyed", "Intent destroyed");
    Toast.makeText(getApplicationContext(), "helloooooooooooo", Toast.LENGTH_LONG).show();
    super.onDestroy();
}

}

Manifest.xml包含..

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.servicedemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

         <service
             android:name=".Myservice"
             android:exported="false"
        />

         <service
             android:name=".Uploadservice"
             android:exported="false"
        />

    </application>



</manifest>

我的问题是文件大小很大时显示

12-02 18:36:35.944: E/dalvikvm-heap(21228): Out of memory on a 90981622-byte allocation.
12-02 18:36:35.944: I/dalvikvm(21228): "IntentService[My service]" prio=5 tid=11 RUNNABLE
12-02 18:36:35.944: I/dalvikvm(21228):   | group="main" sCount=0 dsCount=0 obj=0x41bb0780 self=0x5832c038
12-02 18:36:35.944: I/dalvikvm(21228):   | sysTid=21405 nice=0 sched=0/0 cgrp=apps handle=1479722576
12-02 18:36:35.944: I/dalvikvm(21228):   | schedstat=( 23006625 25262207 18 ) utm=2 stm=0 core=2
12-02 18:36:35.944: I/dalvikvm(21228):   at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:~512)
12-02 18:36:35.944: I/dalvikvm(21228):   at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:488)
12-02 18:36:35.944: I/dalvikvm(21228):   at org.apache.commons.io.FileUtils.readFileToByteArray(FileUtils.java:1764)
12-02 18:36:35.944: I/dalvikvm(21228):   at com.servicedemo.Uploadservice.convertFileToBytes(Uploadservice.java:126)
12-02 18:36:35.944: I/dalvikvm(21228):   at com.servicedemo.Uploadservice.uploadVideo(Uploadservice.java:68)
12-02 18:36:35.944: I/dalvikvm(21228):   at com.servicedemo.Uploadservice.onHandleIntent(Uploadservice.java:47)
12-02 18:36:35.944: I/dalvikvm(21228):   at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
12-02 18:36:35.944: I/dalvikvm(21228):   at android.os.Handler.dispatchMessage(Handler.java:99)
12-02 18:36:35.944: I/dalvikvm(21228):   at android.os.Looper.loop(Looper.java:137)
12-02 18:36:35.944: I/dalvikvm(21228):   at android.os.HandlerThread.run(HandlerThread.java:60)
12-02 18:36:35.949: W/dalvikvm(21228): threadid=11: thread exiting with uncaught exception (group=0x40e962a0)
12-02 18:36:35.954: E/AndroidRuntime(21228): FATAL EXCEPTION: IntentService[My service]
12-02 18:36:35.954: E/AndroidRuntime(21228): java.lang.OutOfMemoryError
12-02 18:36:35.954: E/AndroidRuntime(21228):    at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:512)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:488)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at org.apache.commons.io.FileUtils.readFileToByteArray(FileUtils.java:1764)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at com.servicedemo.Uploadservice.convertFileToBytes(Uploadservice.java:126)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at com.servicedemo.Uploadservice.uploadVideo(Uploadservice.java:68)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at com.servicedemo.Uploadservice.onHandleIntent(Uploadservice.java:47)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at android.os.Handler.dispatchMessage(Handler.java:99)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at android.os.Looper.loop(Looper.java:137)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at android.os.HandlerThread.run(HandlerThread.java:60)

问题在于

private byte[] convertFileToBytes(String iFilePath) throws IOException
    {
        return FileUtils.readFileToByteArray(new File(iFilePath));
    } 

它在Uploadservice.java中定义

此外,是否需要使用

String requestURL = requestUri + "&TotalChunks=" + numOfChunks + "&ChunkCounter=" + chunkNo;

或者我们可以将其删除???

1 个答案:

答案 0 :(得分:0)

这是因为您在上传之前将整个视频读入内存!这对于图像文件可能没问题,但是您不能假设在上传视频时有足够的RAM来存储视频。

您需要以InputStream打开文件,并在从流中读取时上传。

您还可以使用MappedByteBuffer。我会使用流,但看起来好像MappedByteBuffer会更接近您已有的代码。

相关问题