使用HttpURLConnection发送MultipartEntity

6
使用以下代码,我可以将大文件发送到服务器,但是我似乎无法找到如何发送文件和文本(例如用户名、密码等)的方法,并在服务器端接收它。请参考以下代码:
FileInputStream fileInputStream = new FileInputStream(new File(
                   pathToOurFile));
URL url = new URL(urlServer);
            connection = (HttpURLConnection) url.openConnection();
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=\"uploadedVideos\";filename=\""
                    + pathToOurFile + "\"" + lineEnd;
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);
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);
       fileInputStream.close();
        outputStream.flush();
        outputStream.close();

服务器部分:

HttpPostedFile file = HttpContext.Current.Request.Files[0];
string fname = Path.GetFileName(file.FileName);
   file.SaveAs(Server.MapPath(Path.Combine("~/UploadedVideos/" + Date  + "/", fname)));

请任何帮助都将不胜感激。 我知道可以使用HttpClient来完成这个任务,但对于大文件来说它对我不起作用,因此我想使用这种方式。


对于小文件,它能正常工作吗? - ρяσѕρєя K
以上代码适用于任何大小的文件,但我不知道如何发送文件以外的其他数据(字符串文本)。 - Rashad.Z
我之前使用过HttpClient,并且能够使用multipart实体发送额外的数据,但由于某些原因,使用HttpEntity无法发送大文件,所以我使用了上述方法。如果您想让我发布旧方法,我很乐意。 - Rashad.Z
想要发送哪些其他数据? - ρяσѕρєя K
我想要发送一个字符串用户名和密码与文件一起。 - Rashad.Z
只需编写新的边界、内容分配、您的数据和行结尾。对于每个参数都要这样做。该网站上有许多示例。 - greenapps
2个回答

11

请使用此功能。

  private static String multipost(String urlString, MultipartEntity reqEntity) {

        try {
            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setUseCaches(false);
            conn.setDoInput(true);
            conn.setDoOutput(true);

            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.addRequestProperty("Content-length", reqEntity.getContentLength()+"");
            conn.addRequestProperty(reqEntity.getContentType().getName(), reqEntity.getContentType().getValue());

            OutputStream os = conn.getOutputStream();
            reqEntity.writeTo(conn.getOutputStream());
            os.close();
            conn.connect();

            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                return readStream(conn.getInputStream());
            }

        } catch (Exception e) {
            Log.e("MainActivity", "multipart post error " + e + "(" + urlString + ")");
        }
        return null;
    }

    private static String readStream(InputStream in) {
        BufferedReader reader = null;
        StringBuilder builder = new StringBuilder();
        try {
            reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return builder.toString();
    }

在这里,您可以使用MultipartEntiry设置文件、用户名和密码,如下所示。

 private void uploadMultipartData() throws UnsupportedEncodingException {

        MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
        reqEntity.addPart("fileToUpload", new FileBody(uploadFile));
        reqEntity.addPart("uname", new StringBody("MyUserName"));
        reqEntity.addPart("pwd", new StringBody("MyPassword"));
        String response = multipost(server_url, reqEntity);

        Log.d("MainActivity", "Response :"+response);
    }

注意:您需要将httpmime jar添加到您的libs文件夹中。


4
"MultipartEntity已被弃用。" - James Tan
你找到解决方案了吗,@JamesTan? - Android is everything for me
please see my answer - James Tan
设置Content-Length非常重要。 - jet_choong

2

这是我的工作代码,我记得从某个地方复制了它,但现在想不起来了...

package my.com.myapp.utils;

import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

/**
 * This utility class provides an abstraction layer for sending multipart HTTP
 * POST requests to a web server.
 * @author www.codejava.net
 *
 */
public class MultipartUtil {
    private final String boundary;
    private static final String LINE_FEED = "\r\n";
    private HttpURLConnection httpConn;
    protected String charset;
    protected OutputStream outputStream;
    protected PrintWriter writer;
    public boolean cancel = false;
    protected boolean last_item_is_file = false;
    public static String LOG_TAG = "MultipartUtil";
    /**
     * This constructor initializes a new HTTP POST request with content type
     * is set to multipart/form-data
     * @param requestURL
     * @param charset
     * @throws IOException
     */
    public MultipartUtil(String requestURL, String charset, Boolean send_auth)
            throws IOException {
        this.charset = charset;

        // creates a unique boundary based on time stamp
        boundary = "===" + System.currentTimeMillis() + "===";

        URL url = new URL(requestURL);
        httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setUseCaches(false);
        httpConn.setDoOutput(true); // indicates POST method
        httpConn.setDoInput(true);
        httpConn.setRequestProperty("Content-Type",
                "multipart/form-data; boundary=" + boundary);
        httpConn.setRequestProperty("User-Agent", "Android submit");
        //addHeaderField("lang", AppConfig.getInstance().language);
        //addHeaderField("country", AppConfig.getInstance().country);
        //User user = AppConfig.getInstance().get_user();
        /*
        if (send_auth && user != null && user.authentication_token != null && !user.authentication_token.equalsIgnoreCase("")) {
            Log.i(LOG_TAG, "user token: "+user.authentication_token);
            addHeaderField("X-User-Email", user.email);
            addHeaderField("X-User-Token", user.authentication_token);
        } else {
            Log.i(LOG_TAG, "not auth / not logged in");
        }
        */
        // httpConn.setRequestProperty("Test", "Bonjour");
    }

    public PrintWriter setup_writer() throws IOException {
        outputStream = httpConn.getOutputStream();
        writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
                true);
        return writer;
    }

    /**
     * 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();
        last_item_is_file = false;
    }

    /**
     * Adds a upload file section to the request
     * @param fieldName name attribute in <input type="file" name="..." />
     * @param uploadFile a File to be uploaded
     * @throws IOException
     */
    public void addFilePart(String fieldName, File uploadFile)
            throws IOException {
        String fileName = uploadFile.getName();
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append(
                "Content-Disposition: form-data; name=\"" + fieldName
                        + "\"; filename=\"" + fileName + "\"")
                .append(LINE_FEED);
        writer.append(
                "Content-Type: "
                        + URLConnection.guessContentTypeFromName(fileName))
                .append(LINE_FEED);
        writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
        writer.append(LINE_FEED);
        writer.flush();

        FileInputStream inputStream = new FileInputStream(uploadFile);
        byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while (!cancel && (bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.flush();
        inputStream.close();
        if (cancel) {
            writer.close();
            return;
        }

        writer.append(LINE_FEED);
        writer.flush();
        last_item_is_file = true;
    }

    public void addFileStreamPart(String fieldName, String fileName, InputStream inputStream)
            throws IOException {

        writer.append("--" + boundary).append(LINE_FEED);
        writer.append(
                "Content-Disposition: form-data; name=\"" + fieldName
                        + "\"; filename=\"" + fileName + "\"")
                .append(LINE_FEED);
        writer.append(
                "Content-Type: "
                        + URLConnection.guessContentTypeFromName(fileName))
                .append(LINE_FEED);
        writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
        writer.append(LINE_FEED);
        writer.flush();

        byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while (!cancel && (bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }

        outputStream.flush();
        inputStream.close();
        if (cancel) {
            writer.close();
            return;
        }

        writer.append(LINE_FEED);
        writer.flush();
        last_item_is_file = true;
    }

    /**
     * Adds a header field to the request.
     * @param name - name of the header field
     * @param value - value of the header field
     */
    public void addHeaderField(String name, String value) {
        httpConn.setRequestProperty(name, value);
        //writer.append(name + ": " + value).append(LINE_FEED).flush();
        //addFormField("headers["+name+"]", value);
        //writer.append(name + ": " + value).append(LINE_FEED).flush();
    }

    public HttpURLConnection finish() throws IOException {

        if (last_item_is_file)
            writer.append(LINE_FEED).flush();
        writer.append("--" + boundary + "--").append(LINE_FEED);
        writer.close();

        return httpConn;
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接