You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android程序创建的外部存储文件无法在Windows资源管理器显示及FTP上传失败求助

Android 存储与FTP上传问题

问题描述

我是Android开发新手,程序需要创建HTML文件并上传至FTP服务器。手动创建目录和文件时一切正常,但通过代码创建后,Android Studio的Explorer能看到文件在正确目录,Windows资源管理器却看不到对应的目录和文件,推测这导致了FTP上传失败。查阅多篇存储相关文章仍无法解决,请求帮助。我希望能在Windows资源管理器中看到代码创建的文件夹内容。

相关代码

创建本地HTML文件方法

public void createLocalHTML(String codeRes, Context context) throws IOException {
    @SuppressLint("SdCardPath") File internalDir = new File(Environment.getExternalStorageDirectory() + File.separator + "timetracker" + File.separator + getYear() + File.separator + getMonth());
    Log.d("localDir", String.valueOf(internalDir));
    String fileName = codeRes + ".html";
    File internalFile = new File(internalDir, fileName);
    Log.d("localDir", String.valueOf(internalFile));
    if (internalFile.exists()) {
        Log.d("localDir", "file.exists TRUE");
        if (internalFile.canRead()) {
            Log.d("localDir", "file.canRead TRUE");
        } else { Log.d("localDir", "file.canRead FALSE"); }
//            update file in future....
    } else {Log.d("localDir", "file.exists FALSE");}
    if (!internalDir.mkdirs()) {
        internalDir.mkdirs();
        Log.d("mLog", "Directory created in path: " + internalDir);
    } else { return; }
    internalFile.createNewFile();
    FileWriter writer = new FileWriter(fileName, false);
    writer.write(context.getAssets().open("dataTime.html").toString());
    writer.close();
}

FTP上传文件方法

public void sendFileIntoFTP(FTPClient ftpClient, String codeRes) throws URISyntaxException, IOException {
    @SuppressLint("SdCardPath") String sourceFilePath = Environment.getExternalStorageDirectory() + File.separator + "timetracker" + File.separator + getYear() + File.separator + getMonth();
//      Log.d("dirFTP", sourceFilePath);
    String fileName = codeRes + ".html";
    File sourceFile = new File(new URI(sourceFilePath));
    Log.d("dirFTP", String.valueOf(sourceFile));
    InputStream inputStream = new FileInputStream(sourceFile);
    ftpClient.storeFile(fileName, inputStream);
    if (ftpClient.storeFile(fileName, inputStream)) {
        Log.d("dirFTP", "SUCCESS");
    } else {
        Log.d("dirFTP", "ERROR");
    }
    inputStream.close();
}

日志输出(localDir)

2023-11-14 10:44:44.567  6819-6945  localDir                pid-6819                             D  /storage/emulated/0/timetracker/2023/11-2023
2023-11-14 10:44:44.567  6819-6945  localDir                pid-6819                             D  /storage/emulated/0/timetracker/2023/11-2023/003.html
2023-11-14 10:44:44.572  6819-6945  localDir                pid-6819                             D  file.exists TRUE
2023-11-14 10:44:44.573  6819-6945  localDir                pid-6819                             D  file.canRead TRUE

权限配置

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
    tools:ignore="ScopedStorage" />

问题分析与解决方案

1. 文件写入路径错误

createLocalHTML方法中,FileWriter writer = new FileWriter(fileName, false);仅传入文件名,未指定完整路径,导致文件实际写入应用工作目录,而非目标外部存储路径。这是Windows资源管理器看不到文件、FTP上传失败的核心原因。

修复:使用完整文件路径初始化FileWriter:

FileWriter writer = new FileWriter(internalFile, false);

2. 目录创建逻辑错误

当前代码中,若目录已存在或创建成功,会直接return,导致后续文件创建、写入操作完全跳过。

修复:调整目录判断逻辑,仅在目录创建失败时返回:

if (!internalDir.exists()) {
    if (internalDir.mkdirs()) {
        Log.d("mLog", "Directory created in path: " + internalDir);
    } else {
        Log.d("mLog", "Failed to create directory");
        return;
    }
}

3. FTP上传路径错误

sendFileIntoFTP方法中,sourceFilePath是目录路径而非文件路径,导致FileInputStream打开的是目录而非目标HTML文件;且重复调用storeFile会因输入流已耗尽导致第二次上传失败。

修复:拼接完整文件路径,仅调用一次storeFile:

String fileName = codeRes + ".html";
String sourceFilePath = Environment.getExternalStorageDirectory() + File.separator + "timetracker" + File.separator + getYear() + File.separator + getMonth() + File.separator + fileName;
File sourceFile = new File(sourceFilePath);
Log.d("dirFTP", String.valueOf(sourceFile));
if (!sourceFile.exists()) {
    Log.d("dirFTP", "File not found");
    return;
}
InputStream inputStream = new FileInputStream(sourceFile);
boolean success = ftpClient.storeFile(fileName, inputStream);
if (success) {
    Log.d("dirFTP", "SUCCESS");
} else {
    Log.d("dirFTP", "ERROR");
}
inputStream.close();

4. 媒体库刷新(解决Windows可见性)

Android 10+的Scoped Storage机制下,新创建的文件不会自动被媒体库索引,导致Windows通过MTP连接时无法看到。需手动通知媒体库扫描:

在文件创建完成后添加:

MediaScannerConnection.scanFile(context, new String[]{internalFile.getAbsolutePath()}, null,
        (path, uri) -> Log.d("localDir", "File scanned: " + path));

5. 运行时权限检查

需确保在运行时获取对应存储权限:

  • Android 6-9:请求WRITE_EXTERNAL_STORAGE权限
  • Android 10+:引导用户开启MANAGE_EXTERNAL_STORAGE权限

示例代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    if (!Environment.isExternalStorageManager()) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivity(intent);
    }
} else {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
}

内容的提问来源于stack exchange,提问作者Alexandr Borisov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:15:27