Android - 如何将文件名添加到调用 PHP 文件的上传文件函数

Posted

技术标签:

【中文标题】Android - 如何将文件名添加到调用 PHP 文件的上传文件函数【英文标题】:Android - How to add file name to an upload file function that calls a PHP file 【发布时间】:2020-06-06 01:48:38 【问题描述】:

我的 android 应用中有以下 Java 代码 - 在扩展 Application 的 Java 类中:

public static void XSUploadFile(final String filePath, final String fileName, final Activity act, final XSFileHandler handler) 
      new Thread(new Runnable() 
         public void run() 
            upload(filePath, fileName, act, handler);
         
      ).start();
   
   public interface XSFileHandler  void done(String fileURL, String error); 
   public static void upload(String sourceFileUri, String fileName, Activity act, final XSFileHandler handler) 
         HttpURLConnection conn;
         DataOutputStream dos;
         String lineEnd = "\r\n";
         String twoHyphens = "--";
         String boundary = "*****";
         final int code;
         int bytesRead, bytesAvailable, bufferSize;
         byte[] buffer;
         int maxBufferSize = 1024*1024;
         File sourceFile = new File(sourceFileUri);
         try 
               FileInputStream fileInputStream = new FileInputStream(sourceFile);
               URL url = new URL(DATABASE_PATH + "upload-file.php");

               conn = (HttpURLConnection) url.openConnection();
               conn.setDoInput(true); // Allow Inputs
               conn.setDoOutput(true); // Allow Outputs

               conn.setUseCaches(false); // Don't use a Cached Copy
               conn.setRequestMethod("POST");
               conn.setRequestProperty("Connection", "Keep-Alive");
               conn.setRequestProperty("ENCTYPE", "multipart/form-data");
               conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
               conn.setRequestProperty("file", sourceFileUri);
               dos = new DataOutputStream(conn.getOutputStream());
               dos.writeBytes(twoHyphens + boundary + lineEnd);

               dos.writeBytes("Content-Disposition: form-data; name='file';fileName='" + sourceFileUri + "'" + fileName + "\"" + lineEnd);

               dos.writeBytes(lineEnd);
               bytesAvailable = fileInputStream.available();
               bufferSize = Math.min(bytesAvailable, maxBufferSize);
               buffer = new byte[bufferSize];
               bytesRead = fileInputStream.read(buffer, 0, bufferSize);
               while (bytesRead > 0) 
                  dos.write(buffer, 0, bufferSize);
                  bytesAvailable = fileInputStream.available();
                  bufferSize = Math.min(bytesAvailable, maxBufferSize);
                  bytesRead = fileInputStream.read(buffer, 0, bufferSize);
               
               dos.writeBytes(lineEnd);
               dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
               code = conn.getResponseCode();

               if (code == HttpURLConnection.HTTP_OK) 
                  final HttpURLConnection finalConn = conn;
                  act.runOnUiThread(new Runnable() 
                     public void run() 
                        InputStream responseStream = null;
                        try 
                           responseStream = new BufferedInputStream(finalConn.getInputStream());
                           BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
                           String line;
                           StringBuilder stringBuilder = new StringBuilder();
                           int i = 0;
                           while ((line = responseStreamReader.readLine()) != null) 
                              if (i != 0)  stringBuilder.append("\n"); 
                              stringBuilder.append(line);
                              i++;
                           
                           responseStreamReader.close();
                           String response = stringBuilder.toString();
                           responseStream.close();
                           finalConn.disconnect();
                           // Log.i(TAG, "XSUploadFile -> " + response);

                           if (response != null)  handler.done(DATABASE_PATH + response, null);
                            else  handler.done(null, E_401); 

                        // error
                         catch (IOException e)  e.printStackTrace(); handler.done(null, XS_ERROR); 
                     );

               // Bad response from sever
                else 
                  act.runOnUiThread(new Runnable() 
                     public void run()  handler.done(null, XS_ERROR); );
               
               fileInputStream.close();
               dos.flush();
               dos.close();

         // No response from server
          catch (final Exception ex) 
            act.runOnUiThread(new Runnable() 
               public void run()  handler.done(null, XS_ERROR); );
         
   

我这样称呼它:

   // Get demo image path
   Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.demo_img);
   final String filePath = getRealPathFromURI(getImageUri(bmp, ctx), ctx);

    XSUploadFile(filePath, "image.jpg", (Activity)ctx, new XServerSDK.XSFileHandler() 
        @Override
        public void done(String fileURL, String e) 
            if (fileURL != null) 
                hideHUD();
                Log.i("log-", "Uploaded FileURL: " + fileURL);
            
    );

这是我的upload-file.php 脚本:

<?php include '_config.php';

if ($_FILES["file"]["error"] > 0) 
    echo "Error: " .$_FILES["file"]["error"]. "<br>";

 else 
    // Check file size
    if ($_FILES["file"]["size"] > 20485760)  // 20 MB
        echo "ERROR: Your file is larger than 20 MB. Please upload a smaller one.";    
     else  uploadImage(); 

// ./ If


// UPLOAD IMAGE ------------------------------------------
function uploadImage() 
    // generate a unique random string
    $randomStr = generateRandomString();
    $filePath = "uploads/".$randomStr;

    // upload image into the 'uploads' folder
    move_uploaded_file($_FILES['file']['tmp_name'], $filePath);

    // echo the link of the uploaded image
    echo $filePath;


// GENERATE A RANDOM STRING ---------------------------------------
function generateRandomString() 
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i<20; $i++) 
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    
    return $randomString."_".$_POST['fileName'];

?>

我在 Logcat 中得到的结果是这个:

Uploaded FileURL: https://xscoder.com/xserver/uploads/mocpWfxIvtRAacnk1lTV_

我需要做的是将“image.jpg”附加到该 URL 的末尾,所以最终结果应该是这样的:

Uploaded FileURL: https://xscoder.com/xserver/uploads/mocpWfxIvtRAacnk1lTV_image.jpg

我假设它可以在我的 java 类的 XSUploadFile() 函数中完成,也许通过编辑这一行:

dos.writeBytes("Content-Disposition: form-data; name='file';fileName='" + sourceFileUri + "'" + fileName + "\"" + lineEnd);

我尝试了一些编辑,但完全没有成功。

请注意,我无法编辑 PHP 脚本,我有一个 PHP 和 ios SDK,它们都调用该脚本并且工作正常,所以我必须只编辑 Android Java 代码。

【问题讨论】:

请在下面找到答案。 谢谢,我已经编辑了我的问题 没有扩展的ios如何显示图片? 【参考方案1】:

您需要从上传的文件中获取扩展名。请看下面的代码。

$filename = $_FILES["file"]["name"];
$file_extension = end((explode(".", $filename)));
$filePath = 'uploads/' . $randomStr.$file_extension;
move_uploaded_file($_FILES["file"]["tmp_name"], $filePath);

编辑

@xscoder 无法编辑 php,所以我在 java 中给出了一个函数,当你将文件名传递给它时,它会返回文件扩展名。

private static String getFileExtension(String fileName) 
        if(fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0)
        return fileName.substring(fileName.lastIndexOf(".")+1);
        else return "";

您可以将这一行编辑为

dos.writeBytes("Content-Disposition: form-data; name='file';fileName='" + sourceFileUri + "'" + fileName +"."+ getFileExtension(fileName) +"\"" + lineEnd);

注意:在 java 中使用文件时,您需要包含这一行 import java.io.File;

【讨论】:

谢谢,但我无法编辑我的 php 脚本,我忘了在我的问题中提及它,因为我还有一个 PHP 和 iOS SDK 可以按原样调用该文件工作正常,所以我必须只编辑我的 Java 代码 @xscoder 没有扩展 ios如何显示图片? 因为在一个类似的 Swift 函数中,这就是我使用的:body.append("\(fileName)\r\n".data(using: String.Encoding.utf8)!) AND if fileName.hasSuffix(".jpg") body.append("Content-Type:image/png\r\n\r\n".data(using: String.Encoding.utf8)!)。所以我的http请求发送的是文件数据+文件名String,完整的文件名就变成了randomChars_image.jpg。我也必须对我的 Android 代码做类似的工作 @xscoder 您在 php 文件中上传的所有扩展名是什么? 主要是 jpg、png 和 mp4,但我可以上传任何文件,因为我在代码中附加了文件名和扩展名。【参考方案2】:

我从我的 Swift 代码中获得灵感找到了解决方案,我必须将此代码添加到我的 upload 函数中:

dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=\"fileName\"\r\n\r\n" +
                    fileName + "\r\n" +
                    "--" + boundary + "\r\n" +
                    "Content-Disposition: form-data; name=\"file\"; filename=\"file\"\r\n"

            );

所以,最终的 Java 函数现在看起来像这样:

 public static void upload(String sourceFileUri, String fileName, Activity act, final XSFileHandler handler) 
         HttpURLConnection conn;
         DataOutputStream dos;
         String lineEnd = "\r\n";
         String twoHyphens = "--";
         String boundary = "*****";
         final int code;
         int bytesRead, bytesAvailable, bufferSize;
         byte[] buffer;
         int maxBufferSize = 1024*1024;
         File sourceFile = new File(sourceFileUri);

         StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
         StrictMode.setThreadPolicy(policy);

         try 
               FileInputStream fileInputStream = new FileInputStream(sourceFile);
               URL url = new URL(DATABASE_PATH + "upload-file.php");

               conn = (HttpURLConnection) url.openConnection();
               conn.setDoInput(true);
               conn.setDoOutput(true);
               conn.setUseCaches(false);
               conn.setRequestMethod("POST");
               conn.setRequestProperty("Connection", "Keep-Alive");
               conn.setRequestProperty("ENCTYPE", "multipart/form-data");
               conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
               conn.setRequestProperty("file", sourceFileUri);
               dos = new DataOutputStream(conn.getOutputStream());
               dos.writeBytes(twoHyphens + boundary + lineEnd);

            /* HERE'S THE MAGIC CODE :) */
            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=\"fileName\"\r\n\r\n" +
                    fileName + "\r\n" +
                    "--" + boundary + "\r\n" +
                    "Content-Disposition: form-data; name=\"file\"; filename=\"file\"\r\n"

            );


               dos.writeBytes(lineEnd);
               bytesAvailable = fileInputStream.available();
               bufferSize = Math.min(bytesAvailable, maxBufferSize);
               buffer = new byte[bufferSize];
               bytesRead = fileInputStream.read(buffer, 0, bufferSize);
               while (bytesRead > 0) 
                  dos.write(buffer, 0, bufferSize);
                  bytesAvailable = fileInputStream.available();
                  bufferSize = Math.min(bytesAvailable, maxBufferSize);
                  bytesRead = fileInputStream.read(buffer, 0, bufferSize);
               
               dos.writeBytes(lineEnd);
               dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
               code = conn.getResponseCode();

               if (code == HttpURLConnection.HTTP_OK) 
                  final HttpURLConnection finalConn = conn;
                  act.runOnUiThread(new Runnable() 
                     public void run() 
                        InputStream responseStream = null;
                        try 
                           responseStream = new BufferedInputStream(finalConn.getInputStream());
                           BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
                           String line;
                           StringBuilder stringBuilder = new StringBuilder();
                           int i = 0;
                           while ((line = responseStreamReader.readLine()) != null) 
                              if (i != 0)  stringBuilder.append("\n"); 
                              stringBuilder.append(line);
                              i++;
                           
                           responseStreamReader.close();
                           String response = stringBuilder.toString();
                           responseStream.close();
                           finalConn.disconnect();
                           // Log.i(TAG, "XSUploadFile -> " + response);

                           if (response != null)  handler.done(DATABASE_PATH + response, null);
                            else  handler.done(null, E_401); 

                        // error
                         catch (IOException e)  e.printStackTrace(); handler.done(null, XS_ERROR); 
                     );

               // Bad response from sever
                else  act.runOnUiThread(new Runnable() 
                     public void run()  handler.done(null, XS_ERROR); ); 
               fileInputStream.close();
               dos.flush();
               dos.close();

         // No response from server
          catch (final Exception ex) 
            act.runOnUiThread(new Runnable() 
               public void run()  handler.done(null, XS_ERROR); );
         
   

【讨论】:

以上是关于Android - 如何将文件名添加到调用 PHP 文件的上传文件函数的主要内容,如果未能解决你的问题,请参考以下文章

如何在Android Studio添加本地aar包引用

如何在 Wordpress 中的 php 文件上调用 css? [复制]

android如何调用本地html文件

如何在android中使用inflater将一个xml设计调用到另一个xml设计中

如何将自定义挂钩添加到 Woocommerce 的自定义插件

Android:如何调用相机[重复]